Developer documentationAPI v1

Guides

Querying and pagination

Filter, sort, search and page through records, with cursor pagination for integrations that need to go deeper.

GET a list or POST a query

GET /{resource} and POST /{resource}/query use the same read path. GET encodes filters in the singular filter query parameter; POST uses a filters array in its JSON body. POST /query works with a read-only key. Unknown or repeated query parameters return 400 invalid_request.

GET a list or POST a query
ParameterMeaning
page / cursorChoose one pagination mode. Page defaults to 1; start a cursor walk with start.
page_size1–100 records; default 25.
sort / orderA sortable field key, and asc or desc. Default order is newest first.
searchFree-text search on resources with searchable: true; ranks a bounded 500-candidate window.
include_archivedInclude archived records; false by default.
filter / filters, joinStructured filters, combined with and (default) or or.
fieldsComma-separated names in GET; an array in POST /query.
model_idRequired for data_model_records; does not apply to other resources.

Use certified filters

Each filter has field, op and, when needed, value. Fields, operators and values are checked against the workspace’s capabilities. A native field uses its field key; custom fields use the described filter_key; related fields use rel:<foreign-key-column>.<column>.

Use certified filters
OperatorsValue
eq, ne, gt, gte, lt, lteA compatible scalar.
iLike, notILikeCase-insensitive text matching.
inArray, notInArrayAn array of compatible values.
isBetweenA two-value range.
isEmpty, isNotEmptyNo value needed.
Filter companies
curl --fail-with-body --request POST "$SQUARIO_API_BASE/companies/query" \
  --header "Authorization: Bearer $SQUARIO_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{
    "filters": [{ "field": "name", "op": "iLike", "value": "Northfold" }],
    "join": "and",
    "page_size": 25,
    "fields": ["name"]
  }'
Filter companies
curl --fail-with-body --get "$SQUARIO_API_BASE/companies" \
  --header "Authorization: Bearer $SQUARIO_API_KEY" \
  --data-urlencode 'filter=[{"field":"name","op":"iLike","value":"Northfold"}]' \
  --data-urlencode 'fields=name' \
  --data-urlencode 'page_size=25'

Read the pagination metadata

A list returns data and meta. Page mode includes page, page_size, total and has_more. total_is_capped: true means total is a lower bound. Page numbers address an offset window through 10,000; requests past the permitted page return 400 with details.max_page. For exports and deep synchronisation, use cursors.

List response shape
{
  "data": [{ "id": "c91b7028-f985-4bc1-9f75-c76533c3133a", "name": "Northfold" }],
  "meta": { "page": 1, "page_size": 25, "total": 1, "has_more": false }
}

Walk with an opaque cursor

Send cursor=start, then send the response’s meta.next_cursor unchanged until it is null. Do not also send page. Keep filters, sort and other query settings stable throughout the walk. A cursor is a position, not a snapshot of a changing workspace.

  • Cursor responses carry page_size, next_cursor, cursor_supported, total and has_more.
  • Free-text relevance sorting cannot be walked; cursor_supported is false on its first page. Use page mode for that query.
  • A positioned cursor that does not match the query returns 400. Restart the walk after changing the sort or filters.
  • Treat cursors as opaque. Do not decode, edit or manufacture them.
Walk every page
const base = process.env.SQUARIO_API_BASE?.replace(/\/$/, "");
const key = process.env.SQUARIO_API_KEY;
if (!base || !key) throw new Error("Set SQUARIO_API_BASE and SQUARIO_API_KEY");

let cursor = "start";
while (cursor !== null) {
  const url = new URL(`${base}/companies`);
  url.searchParams.set("cursor", cursor);
  url.searchParams.set("page_size", "100");
  url.searchParams.set("fields", "name");

  const response = await fetch(url, {
    headers: { Authorization: `Bearer ${key}` },
    signal: AbortSignal.timeout(30_000),
  });
  const body = await response.json();
  if (!response.ok) throw new Error(`${body.error.code} (${body.error.request_id})`);
  if (!body.meta.cursor_supported) throw new Error("Use page mode for this sort");

  for (const record of body.data) console.log(record.id, record.name);
  cursor = body.meta.next_cursor;
}