Concepts

Pagination, filtering and search

limit and cursor, filters per resource, search, and the sync pattern with updated_since.

Lists come in pages#

Every list returns the newest records first:

JSON
{
  "object": "list",
  "data": [ { "object": "client", "id": "…" } ],
  "has_more": true,
  "next_cursor": "MjAyNi0xMC0xN1QwOTozMDowMC4wMDBafDZmMWMy…"
}
  • limit — 1 to 200, default 50.
  • cursor — pass next_cursor from the previous page to get the next one. When has_more is false, you have everything.

Cursors stay correct while new records are added: you never get a record twice or miss one in between.

Terminal
curl "$QUILO_URL/api/v1/sales?limit=200&cursor=MjAyNi0x…" -H "Authorization: Bearer $QUILO_API_KEY"

Fetch every page (JavaScript)#

JavaScript
async function all(path) {
  const out = [];
  let cursor = null;
  do {
    const url = new URL(`${process.env.QUILO_URL}/api/v1/${path}`);
    url.searchParams.set('limit', '200');
    if (cursor) url.searchParams.set('cursor', cursor);
    const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.QUILO_API_KEY}` } });
    if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
    const page = await res.json();
    out.push(...page.data);
    cursor = page.has_more ? page.next_cursor : null;
  } while (cursor);
  return out;
}

Filters#

Each resource has its own filters, listed in the API reference. Combine as many as you like; all must match.

Terminal
# open urgent tasks of one client
curl "$QUILO_URL/api/v1/tasks?client_id=5d2c1b0a-…&status=todo&priority=urgent" -H "Authorization: Bearer $QUILO_API_KEY"

# sales in October 2026
curl "$QUILO_URL/api/v1/sales?purchased_from=2026-10-01&purchased_to=2026-10-31" -H "Authorization: Bearer $QUILO_API_KEY"

Unknown parameters are refused with 400 invalid_request, so a misspelt filter never returns everything by accident.

Search clients#

q searches first name, last name, company, email and phone (at least 2 characters, not case-sensitive):

Terminal
curl "$QUILO_URL/api/v1/clients?q=marti" -H "Authorization: Bearer $QUILO_API_KEY"

To find one client by email, use the exact filter email= instead; it is faster and not case-sensitive.

Keeping another system in sync#

Clients have updated_at. Save the time you started each sync and ask only for what changed since the last one:

  1. Remember started = now().
  2. GET /clients?updated_since=<last_started>&limit=200, following next_cursor until has_more is false.
  3. Upsert each client in your system by id.
  4. Store started as last_started for next time.

For other resources use created_since to pick up new records.