Skip to main content
Every collection returns the same envelope:
links.next is a cursor. Send it back as the cursor parameter — on a POST /search, as cursor in the body — until it is null:

Pages stay put while records change

Contacts, organizations and deals are paged from the last record you received, not by position. A record created or deleted while you walk the list never makes you see a record twice or miss one, and a record edited mid-walk shows up again later with its new values. That is what makes a sync with updated_since safe — see Syncing.

Treat the cursor as opaque

Do not parse, construct, or store a cursor beyond one walk. Its contents are an implementation detail and change without notice. A cursor is only valid for the query that produced it. Send it with the same filters and sort; anything else — a cursor you built, one from another endpoint, or one replayed with different filters — returns 400 invalid_cursor.

There is no total count

The response tells you whether another page exists (meta.has_more), not how many records there are in total. Counting the filtered set would mean a second full scan on every page, which gets slower exactly as a workspace grows. If you need a count, page through and count what you receive.

Sorting

Pass sort to order a collection, for example sort=-created_at for newest first or sort=updated_at to walk changes in order. Prefix a key with - for descending; records without a value sort last either way.

Choosing a limit

limit defaults to 50 and accepts up to 200. Larger pages mean fewer round trips; smaller pages mean faster individual responses. For a bulk sync, 200 is usually right.