Reference
Filtering, sorting and paging
Every read is a Query Specification: a JSON object sent as the q parameter of the rows endpoint, or as the body of the query endpoint.
The Query Specification
{
"select": ["reference", "title", "country", "published_on"],
"filters": [
{ "field": "country", "operator": "in", "value": ["KE", "UG"] },
{ "field": "published_on", "operator": "gte", "value": "now-30d" },
{ "field": "estimated_value", "operator": "lt", "value": 100000 }
],
"search": { "query": "medical equipment", "fields": ["title"] },
"sort": [{ "field": "published_on", "direction": "desc" }],
"limit": 50
}| Member | Meaning |
|---|---|
select | The fields to return. Left out, every field you may read. |
filters | Conditions every row must meet, each a field, an operator and a value. |
search | Words to find in the fields the publisher made searchable. |
sort | The order, by fields the publisher made sortable, ascending or descending. |
limit | How many rows a page holds, up to the dataset's maximum. |
cursor | Where the next page starts: the next_cursor of the page before. |
offset | Rows to skip. Capped, because a deep offset reads what it skips: prefer the cursor. |
Every member is optional. An empty specification is the first page of every field you may read, in the dataset's own order.
Filter operators
| Operator | Matches rows whose field is |
|---|---|
eq | Equal to the value. |
neq | Not equal to the value. |
gt | Greater than the value. |
gte | Greater than or equal to the value. |
lt | Less than the value. |
lte | Less than or equal to the value. |
contains | Text containing the value. |
starts_with | Text starting with the value. |
ends_with | Text ending with the value. |
in | Equal to one of the values in a list. |
not_in | Equal to none of the values in a list. |
is_null | Has no value; the filter takes no value. |
is_not_null | Has a value; the filter takes no value. |
matches | Text matching the regular expression given as the value. |
Filters combine with AND. A range is two filters on one field, such as gte and lt.
Values
A value's JSON type must suit the field: a string for text, a whole number for an integer, a number for a decimal, true or false for a boolean.
A date is written YYYY-MM-DD. A time is written YYYY-MM-DDTHH:MM:SS, with up to six decimal places of a second; a time with a zone ends in Z or ±HH:MM and is compared in UTC.
A date, or a time with a zone, can be relative to the request: now, or now plus or minus minutes, hours, days or weeks, such as now-7d.
Values are always sent as data, never as part of a statement, whatever they contain.
What the publisher allows
The dataset's publisher decides which fields can be read, filtered, sorted and searched, and with which operators.
A specification that asks for anything else is refused with 400 and the code query_invalid. The details list every reason at once, each with one of these codes.
unknown_fieldfield_not_returnablefield_not_filterablefield_not_sortablefield_not_searchableoperator_not_permittedvalue_requiredvalue_not_permittedvalue_must_be_listvalue_must_not_be_listlimit_exceededsearch_not_supporteddataset_mismatchvalue_type_mismatchlimit_invalidoffset_invalidoffset_exceededpagination_conflictcursor_invalidsort_direction_invalidcost_exceededPaging
A page holds limit rows, or the dataset's default. While more rows follow, the page carries next_cursor: send it back as cursor, with the same filters and sort.
A cursor is sealed. It cannot be read or built, and a changed one is refused.
Conditional requests
Every page has an ETag. Send it back in If-None-Match when you read rows with GET: a page that has not changed is answered 304, with no body, for a tenth of the credits.
A query sent with POST is not answered 304: a matching If-None-Match there is answered 412 with the code precondition_failed.