Skip to main content

1. Accumulate the records you need

For a customer reporting store, first read /company and accumulate the reference catalogs and /team-members. Page /accounts, /contacts, /locations, /jobs, /job-appointments, and /job-assignments, upserting by ID. Join an invoice’s job_id to jobs, an appointment’s job_id to jobs, and an assignment’s appointment_id to appointments and team_member.id to members. Count each visit once before joining multiple assignments. For example, two assignments on one visit are two member assignments, one visit, and one job. Segment invoice values by the invoice’s recorded dimensions; this API does not allocate revenue across participating members. Persist the exact query and its next cursor after each successfully committed page. If you flatten a document into several tables, commit the parent and replacement child sets together before advancing the cursor. Start with a small page size when measuring response size.

2. Preserve each resource’s grain

3. Refresh a bounded scope

For subsequent refreshes, read new records by creation range, parent edits where supported, and active/recent job IDs with their visits and assignments. Re-read selected known older IDs to capture corrected child state; an open-only or incomplete-only query misses records that moved out of that state. Small reference catalogs and member profiles can be reread in full. These approaches let customers control refresh scope without repeatedly downloading every company record, but they do not guarantee complete change capture. Invoice updated_at tracks its underlying parent row. Payment updated_at is the recorded parent edit time and is null when unavailable. Related payment statuses, allocations, children, or business references may change without advancing these timestamps. Refunds expose created_at and occurred_at, with no updated_at field or updated_since filter. Choose windows based on how far back your business normally corrects data. Parent updated_since is useful where supported, but it does not capture every child or relationship edit. Retain the IDs of records that were active or outstanding so you can reread them after they leave that state.

4. Reconcile state changes

For a local reporting store, page the collections, upsert parents by ID, and replace each refreshed parent’s embedded child set when flattening it. Later, read recent activity and parent edits with supported filters. To refresh open invoices, also re-read previously open IDs without a status restriction; an invoice that became PAID would disappear from an open-only query. Alternatively, replace a scoped local AR result after paging the entire current open-invoice query. That replacement affects the current result, not the customer’s broader invoice history. Periodic reads of selected older periods can capture corrections. A missing row in a filtered response does not prove deletion. A customer-controlled broader reread is needed when you require confidence about older corrections or hard deletions. Never delete a locally stored record just because it is absent from a filtered page. The API has no snapshot, tombstone stream, or guaranteed change feed.

Pick the relevant refresh rules

Refresh limits differ by resource. Read Work and customers, Leads and estimates, Time reporting, Equipment and forms, Job profitability, and Saved revenue attribution for the records you store.