API
Sort, filter and search
One JSON query to sort, filter, search, pick fields, join related records and count.
List records takes an optional query parameter: a JSON object, URL-encoded. GraphQL accepts the same object. The examples use a contacts collection and reuse base and token from earlier pages.
Send a query
GET /api/v1/workspaces/:workspace/collections/:collection/records
curl --get 'http://127.0.0.1:8080/api/v1/workspaces/YOUR_WORKSPACE_ID/collections/YOUR_COLLECTION_ID/records' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--data-urlencode 'limit=20' \
--data-urlencode 'query={"filters":[{"field":"is_customer","operator":"eq","value":true}],"sort":[{"field":"deal_value","descending":true}],"fields":["full_name","deal_value"],"meta":["filter_count"]}' const query = {
filters: [{ field: 'is_customer', operator: 'eq', value: true }],
sort: [{ field: 'deal_value', descending: true }],
fields: ['full_name', 'deal_value'],
meta: ['filter_count']
};
const params = new URLSearchParams({ limit: '20', query: JSON.stringify(query) });
const res = await fetch(`${base}/records?${params}`, {
headers: { Authorization: `Bearer ${token}` }
});
const { data, meta } = await res.json(); query, _ := json.Marshal(map[string]any{
"filters": []map[string]any{{"field": "is_customer", "operator": "eq", "value": true}},
"sort": []map[string]any{{"field": "deal_value", "descending": true}},
"fields": []string{"full_name", "deal_value"},
"meta": []string{"filter_count"},
})
params := url.Values{"limit": {"20"}, "query": {string(query)}}
req, _ := http.NewRequest("GET", base+"/records?"+params.Encode(), nil)
req.Header.Set("Authorization", "Bearer "+token)
res, err := http.DefaultClient.Do(req) import json
query = {
"filters": [{"field": "is_customer", "operator": "eq", "value": True}],
"sort": [{"field": "deal_value", "descending": True}],
"fields": ["full_name", "deal_value"],
"meta": ["filter_count"],
}
res = requests.get(
f"{base}/records",
headers={"Authorization": f"Bearer {token}"},
params={"limit": 20, "query": json.dumps(query)},
) The counts you ask for appear in meta, next to pagination:
{
"pagination": { "limit": 20, "offset": 0, "count": 20, "has_more": true },
"filter_count": 50,
"total_count": 126
} Options
| Option | What it does |
|---|---|
filters | Up to 8 conditions. All must match. Each has field, operator and value. |
sort | Up to 3 fields, each with field and descending. Order is stable and nulls come last. |
fields | Return only these fields. Leave it out to get every field. |
search | Every word must match at least one search field. |
search_fields | Fields to search. Without it, every string and text field is searched. |
joins | Up to 3 lookups into other collections, up to 8 fields each. |
meta | total_count counts all rows, filter_count counts rows that match. Off unless asked, to keep reads fast. |
Filter operators
| Operator | Means | Works on |
|---|---|---|
eq | equals | every type except JSON |
ne | does not equal | every type except JSON |
gt, gte | greater than, or equal | numbers and dates |
lt, lte | less than, or equal | numbers and dates |
contains | contains the text | string and text |
null, not_null | is empty, is not empty (no value) | every type, including JSON |
Booleans only support eq and ne. Dates are compared in UTC.
Join related records
A join reads fields from a matching record in another collection. collection is the other collection’s ID. target_field is the field to match on; leave it out to match on id.
{
"joins": [
{
"field": "company",
"collection": "19c2b406b68223b96809deaead4b34e9",
"target_field": "name",
"fields": ["industry"]
}
]
} The joined fields appear under _related:
{
"full_name": "Citra Lestari",
"company": "FinHub",
"_related": { "company": { "industry": "Fintech" } }
} If nothing matches, the value is null. Joins only read; they create no foreign keys.
Exports
Export accepts filters, sort and search, and always returns every field. fields and meta are rejected there.
Troubleshooting
- 400
invalid_input: check the limits (8 filters, 3 sorts, 3 joins, 8 fields per join), the operator name and the value type. - A join is null: the source value must equal the target field in the other collection.
- No counts in
meta: addtotal_countorfilter_counttometa.