Getting started

Pagination and rate limits

Anything that sweeps a whole workspace, a nightly reconciliation job most of all, runs into both of these. Here is what to expect so you do not discover the limits in production.

Pagination

List endpoints take limit (1 to 100, default 25). Endpoints that support paging also take offset (default 0) and return has_more, limit, and offset alongside data.

has_moremeans “the page came back full”, not “there are exactly N rows left”. Exact totals would mean counting the whole table on every request, which gets slower as a workspace gets busier, so we do not do it. Keep requesting pages until has_more is false. The last page is often empty, and that is normal.

Results are ordered deterministically, with a unique tiebreak column after the sort column, so two records sharing a date cannot swap places between requests and cause a page boundary to skip one.

Which endpoints page

/v1/expenses supports offset and returns has_more. The older resource endpoints (/v1/contacts, /v1/opportunities, /v1/tasks, /v1/users, /v1/pipelines, /v1/stages) accept limit only and return a bare { data }. On those, narrow with the filter parameters rather than trying to walk the full collection.

Rate limits

Requests to /api/v1/ are rate limited at the edge to 100 requests per minute per IP address, measured in a fixed one-minute window. The limit is per source IP, not per API key, so several integrations calling from one host share the budget.

An over-limit request receives 429 with a Retry-After header giving the seconds until the window resets. Write your client to honour it: sleep for Retry-After and retry, rather than retrying immediately. A 429 is always safe to retry, since the request never reached the resource.

Limits are enforced per region, so a globally distributed caller may observe a slightly higher effective ceiling. Do not design against that; treat 100 per minute as the budget.

Writing a sweep that behaves

  • Prefer webhooks to polling. A sweep should be the backstop that catches what a delivery missed, not the primary path.
  • Filter server-side. On expenses, unreconciled_by plus a date floor turns “page the entire history and diff it” into a handful of requests.
  • Ask for limit=100. Fewer, larger pages cost less of the budget than many small ones.
  • Run one request at a time. Fanning out 20 parallel pages from one host is the fastest way to hit the ceiling.
  • Handle 429 and 5xx with backoff; treat 4xx other than 429 as a bug in the request, not something to retry.

Errors

Every error response uses the same envelope. See the errors reference for the full list of codes.