Read every page
Collections default to 50 parent records per page, with a maximum of 100.data contains the records, pagination.next_cursor contains a continuation token or null, and meta supplies request ID, generation time, and company timezone. Follow the cursor until null. Keep the same company, endpoint, and filters; the page size may change between requests. Most timestamped collections order by created_at, then id, ascending. Equipment, form responses, job financials and revenue attributions order by UUID id ascending; job classes order by code id ascending. These orders are fixed. Cursors are opaque and cannot be transferred to another company or endpoint. Report rows follow the same page-size rules.
example-opaque-cursor illustrates the format; only a real API response would supply a usable token. Both list and detail reads return the same invoice shape. Page limits apply to parents, never silently to their children. Large documents may therefore produce larger responses even at limit=1.
Encode filters
Omit a filter to leave it unrestricted, and omitcursor to start the first page. A null query-schema default represents an omitted value; do not send the literal string null or an empty value.
Combine documented filters with AND. Repeated ids or status values mean OR within that field; use ids=ID_A&ids=ID_B, not comma-separated values. Up to 100 IDs may be supplied. Foreign or missing IDs contribute no list results. Repeated scalar parameters, empty values, invalid UUIDs, unknown query parameters, and unsupported filters return 400. Valid filters matching no records return an empty page with a null cursor.
created_from and created_before are inclusive/exclusive instants. Invoices and payments support updated_since as an inclusive parent-row edit instant; payments with null updated_at do not match it. Refunds do not support this filter. issued_from/issued_before and occurred_from/occurred_before are inclusive/exclusive company-local dates. A supplied upper bound must be later than its lower bound. Null dates do not match date filters. Invoice lists include every status by default; status=OPEN provides AR detail. The invoice-activity summary defaults to OPEN and PAID instead.
Use a query-string encoder rather than assembling cursor values or timestamp offsets by hand:
Refresh after the first pass
Keep successful pages when a request fails and retry the same cursor. Treat a multi-page report as incomplete until its last page succeeds. See Build a reporting store for refresh and reconciliation strategies. Reads use latest corrected records. A cursor andgenerated_at do not freeze data across requests. The API offers no guaranteed incremental synchronization or deletion feed, and an updated_since query does not cover all dependent changes. Clients may observe corrections between pages; retry or refresh the relevant query when reconciling current results. Responses should be treated as private company data and use Cache-Control: private, no-store.