Introduction
The Bloom REST API allows you to programmatically interact with the Bloom data platform.
Client requirements
HTTPS
All requests must be made over HTTPS, or it will be rejected
and the API will return a 406 Not Acceptable HTTP status code with an error object.
Headers
Requests must include the following headers:
| Request method | Header | Value |
|---|---|---|
| All | Accept |
application/json |
POST, PATCH, PUT |
Content-Type |
application/json |
Requests missing a required header will be rejected and the API will return a 400 Bad Request HTTP status code
with an error object.
Requests which require authentication must also include one of the following headers:
| Header | Value |
|---|---|
Authorization |
Bearer: Bearer token |
X-Api-Key |
API key |
Bearer tokens can be obtained by following the authentication instructions. An API key can be obtained by using the user keys endpoint.
Private endpoints missing a required authentication header will be rejected and the API
will return a 401 Unauthorized HTTP status code with an error object.
Rate limits
Rate limits are in place as a defensive measure against intended or unintended excessive use. The Bloom API enforces the following rate limits:
| Endpoint type | Rate limit (per minute) |
|---|---|
| Authentication | 3 |
| Public | 10 |
| Assets | 300 |
| Private | 300 |
Requests that exceed the rate limit will be rejected and the API will return a 429 Too Many Requests HTTP status code
with an error object.
The following HTTP headers are returned with all API responses and explain your current rate limit status:
| Header | Description |
|---|---|
X-RateLimit-Limit |
Request limit (per minute) |
X-RateLimit-Remaining |
Number of requests remaining |
X-RateLimit-Reset |
Time until full limit reset (in seconds) |
Retry-After * |
Time (in seconds) until another request can be made |
* The Retry-After header is only returned when the rate limit has been exceeded
and a 429 Too Many Requests response is returned.
HTTP response codes
The Bloom API uses conventional HTTP response codes to indicate the success or failure of an API request.
In general, codes in the 2xx range indicate success, codes in the 4xx range indicate a client error,
and codes in the 5xx range indicate an internal error with the Bloom API (these are rare).
HTTP response codes in the 4xx and 5xx range will always be returned as an error object.
Bad requests (e.g., invalid or missing parameters) will be rejected and the API will return a 400 Bad Request HTTP
status code with an error object.
Requests that receive a 400 Bad Request response should not be repeated without modifications.
Requests to a private endpoint requiring missing permissions will be rejected and the API will return
a 403 Forbidden HTTP status code with an error object.
If the API is temporarily undergoing maintenance or repairs, the request will be rejected and the API will return a
503 Service Unavailable HTTP status code with an error object.
A Retry-After header indicating the number of seconds to wait until the server is expected to become available will also be returned.
Dates and times
All dates and times sent to and received by the Bloom API are in UTC (Coordinated Universal Time) time zone.
Schemas
All resource data is returned in the top-level data property of the JSON response.
Example:
{
"data": {
"id": "01994eef-297a-7d28-9886-a966c8b7d011",
"tenant": "01988bb8-1cfb-7c87-9326-93op0349288e",
"location": "0198cf97-47e0-7930-bfa8-f480a0614068",
"contact": "0198a9f3-8955-7732-ae42-4eb52466ed75",
"setting": "onsite",
"unit": "01988bb8-20a3-741a-80c7-bbfbfe3a9698",
"time_in": "2025-09-15 19:52:00",
"time_out": "2025-09-15 19:52:30",
"archived_at": null,
"created_at": "2025-09-15 19:52:00",
"updated_at": "2025-09-15 19:52:30"
}
}
Metadata
Adding ?meta=true to any endpoint will return metadata associated with the request in the top-level meta property
of the JSON response.
Meta object
{
"version": "1.13.1",
"client_ip": "12.34.56.789",
"request_id": "4c33d199d8",
"elapsed": "0.057",
"time": "2026-07-03T06:05:07+00:00"
}
- versionreadonly required stringThe version of the Bloom API that processed the request.
- client_ipreadonly required stringThe IP address of the client that made the request.
- request_idreadonly required stringA unique identifier for the request.
- elapsedreadonly required stringThe time elapsed (in seconds) to complete the request.
- timereadonly required stringThe UTC timestamp in ISO 8601 format when the request was completed.
Base URL
The base URL for all incoming requests is https://api.bloomdb.com/v1.
Health check
To check the health of the API, a GET request to /server/status should return a
200 HTTP status code. No authentication or defined headers are required.
Example response:
{
"data": {
"status": "OK"
}
}
Collection pagination
Page size
Resource collection endpoints will return a maximum of 50 resources per page by default.
You may specify a different page size by using the limit query parameter.
The maximum page size is 500 resources per page.
For example, to request 100 resources per page, you would use the following query parameter: ?limit=100.
Pagination method
The Bloom API supports both page-based and cursor-based pagination methods.
You may specify a pagination method by using the pagination query parameter. Valid values are:
page- Page-based paginationcursor- Cursor-based pagination
When the pagination query parameter exists, pagination metadata will be returned with the collection in the top-level
pagination property of the JSON response.
Example when using page-based pagination:
{
"pagination": {
"results": {
"current": 50,
"total": 66843,
"from": 1,
"to": 50
},
"page": {
"size": 50,
"current": 1,
"previous": null,
"next": 2,
"total": 1337
}
}
}
Page-based fields
- results.currentreadonly integerTotal number of resources returned in the current request.
- results.totalreadonly integerTotal number of resources existing.
- results.fromnullable readonly integerThe index of the first resource returned in the current request.
- results.tonullable readonly integerThe index of the last resource returned in the current request.
- page.sizereadonly integerThe number of resources returned per page in the current request.
- page.currentreadonly integerThe current page number in the current request.
- page.previousnullable readonly integerThe previous page number, or
nullif not existing. - page.nextnullable readonly integerThe next page number, or
nullif not existing. - page.totalreadonly integerThe total number of pages existing.
Example when using cursor-based pagination:
{
"pagination": {
"results": {
"current": 50
},
"cursor": {
"first": "MDE5ZjA5MzMtZmUwYS03NjI1LTlkY2ItMzJlMGQ0ZjQ3N2U2",
"last": "MDE5ZTQ1NzctODI0Zi03NDJkLTlhZWUtZjAxM2E2NjVmNjA1"
}
}
}
Cursor-based fields
- results.currentreadonly integerTotal number of resources returned in the current request.
- cursor.firstreadonly stringThe cursor of the first resource returned in the current request.
- cursor.lastreadonly stringThe cursor of the last resource returned in the current request.
To request a specific page or cursor, you may use one of the following query parameters:
| Pagination method | Query parameter | Description |
|---|---|---|
| Page | page |
Requested page number |
| Cursor | before |
Request one page before a given cursor |
| Cursor | after |
Request one page after a given cursor |
Sparse fieldsets
The Bloom API supports returning only specific fields of a resource by using the fields query parameter.
Limiting the returned fields to only those which are needed is extremely helpful in reducing the payload size
and API response times.
Sparse fieldsets can be requested as many as 4 levels deep using dot notation.
If the field type is a JSON object, keys can be selected using the format of FIELD->KEY.
The field will be returned as a JSON object with only the requested keys.
Fields which do not exist are returned with a value of null.
Examples:
?fields=*.*- Returns all fields of the resource up to two levels deep.?fields=name,email,phone_home- Returns only thename,email, andphone_homefields of the resource.?fields=id,extra->api->version- Returns theidfield of the resource, as well as theapi.versionkey of theextraJSON object field.?fields=*,contact.name,contact.email- Returns all fields of the resource, as well as thenameandemailfields of thecontactrelationship.
Aggregation
Aggregate functions allow you to perform calculations on a collection of resources and return a single value.
When the aggregate query parameter exists, aggregate data will be returned with the collection in the top-level
aggregate property of the JSON response.
Supported aggregate functions:
AVG- Returns the average value of a numeric field.AVG_DISTINCT- Returns the average value of a numeric field, ignoring duplicate values.COUNT- Returns the number of resources in the collection.COUNT_DISTINCT- Returns the number of distinct values of a field in the collection.MAX- Returns the maximum value of a numeric field.MIN- Returns the minimum value of a numeric field.SUM- Returns the sum of a numeric field.SUM_DISTINCT- Returns the sum of a numeric field, ignoring duplicate values.
Example aggregate query parameter: ?aggregate=[{"COUNT":"*"},{"SUM":"amount"}]
The returned aggregate data will be an associative array of the requested aggregate functions and their results.
Example aggregate response:
{
"aggregate": {
"*": {
"COUNT": 110
},
"amount": {
"SUM": 6580
}
}
}
Searching
You may search by all string and text type fields within a collection using the search query parameter.
The value of the search parameter is the case-insensitive string to search for.
This is an easy way to search for items without creating complex filters,
although it is far less customizable and less optimized.
For example, to search a collection of resources for the string "meeting",
you would use the following query parameter: ?search=meeting.
Sorting
You may sort a collection by one or more fields using the sort query parameter.
The value of the sort parameter is a comma-separated list of fields to sort by.
By default, the API will sort in ascending order. To sort in descending order, prefix the field name with a minus sign (
-).
For example, to sort a collection of resources by created_at in descending order and then by name in ascending
order,
you would use the following query parameter: ?sort=-created_at,name.
Filtering
The Bloom API supports filtering a collection by one or more fields using the filter query parameter.
This allows you to retrieve only the resources that match a specified criteria.
Filtered fields can be requested as many as 4 levels deep using dot notation.
Available operators
| Operator | Description |
|---|---|
eq |
Equals |
!eq |
Does not equal |
lt |
Less than |
gt |
Greater than |
le |
Less than or equal to |
ge |
Greater than or equal to |
sw |
Starts with |
!sw |
Does not start with |
isw |
Starts with (case-insenstivie) |
!isw |
Does not start with (case-insensitive) |
ew |
Ends with |
!ew |
Does not end with |
iew |
Ends with (case-insensitive) |
!iew |
Does not end with (case-insensitive) |
has |
Has |
!has |
Does not have |
ihas |
Has (case-insensitive) |
!ihas |
Does not have (case-insensitive) |
in |
In |
!in |
Not in |
null |
Is null |
!null |
Is not null |
The in and !in operators accept multiple comma-separated values.
The null and !null operators accept one of two values: true or false.
Filter syntax
The top level filter must be an array of filter rules. For example:
[
{
"field": {
"operator": "value"
}
}
]
The field can exist on the current collection or a related resource.
The operator must be any valid filter operator as described above.
The value can be any fixed value, or a dynamic variable.
For example, to retrieve a collection of activities whose title contains the case-insensitive word
"meeting", the requested endpoint would be: /tenants/{{tenantId}}/activities?filter=[{"title":{"ihas":"meeting"}}].
Filter rules can be grouped by placing them within an array keyed as _and or _or.
For example:
[
{
"name": {
"sw": "N"
}
},
{
"_or": [
{
"_and": [
{
"name": {
"sw": "S"
}
},
{
"email": {
"!null": true
}
}
]
}
]
}
]
The above example will filter the collection by results whose name starts with N,
or those whose name starts with S and whose email is not null.
Another example:
[
{
"tenant": {
"eq": "018fa64b-93f9-7b36-a7b0-e2403b27437b"
}
},
{
"member.contact": {
"eq": "018fa64b-93fb-7c46-84a4-9a9264f1d942"
}
},
{
"archived_at": {
"null": true
}
},
{
"_and": [
{
"_or": [
{
"date_from": {
"ge": "$DATE(-1 year)"
}
},
{
"date_to": {
"ge": "$DATE(-1 year)"
}
}
]
}
]
}
]
The above example will filter the collection by results whose tenant and member.contact fields match the given values,
whose archived_at field is null, and whose date_from or date_to fields are greater than or equal to one year ago.
Available dynamic variables
| Variable | Description |
|---|---|
$TIME(<adjustment>) |
The current UTC timestamp plus/minus a given interval |
$DATETIME(<adjustment>) |
The current UTC datetime in Y-m-d H:i:s format plus/minus a given interval |
$DATE(<adjustment>) |
The current UTC date in Y-m-d format plus/minus a given interval. |
$TIME |
The current UTC timestamp |
$DATETIME |
The current UTC datetime in Y-m-d H:i:s format |
$DATE |
The current UTC date in Y-m-d format |
Example:
[
{
"created_at": {
"gt": "$DATE(- 1 year)"
}
}
]
The above example will filter the collection by results whose created_at field is greater than one year ago.
Meta objects
Some resources have a meta field which accepts an object containing additional information about the resource.
The meta field is a JSON object which can contain any number of key-value pairs.
Updating the meta field will merge the new key-value pairs with the existing ones,
and will not overwrite any existing keys unless they are explicitly included in the update.
To remove an existing key from the meta object, set the value of the key to null in the update request.