pagination: { limit, cursor?, hasMore } envelope so callers can iterate without page-counting math.
The Pagination Envelope
Endpoints That Paginate
Every list endpoint acceptslimit (1-100) + cursor and returns the pagination envelope. The default limit is 100 except where noted.
Single-Resource Reads (Identity in the Query)
Reads are flat: there is no separate get-one path. To fetch one row, pass its id key to the resource’s list endpoint and readdata[0]. Detail mode
returns { data: [row] } with no pagination object, since there is
nothing to page through. ?include= opt-ins embed the heavier detail:
When the id misses, most detail reads return a resource-specific
404:
EMAIL_NOT_FOUND, AUDIENCE_NOT_FOUND, SEND_NOT_FOUND, DOMAIN_NOT_FOUND,
AUTOMATION_RUN_NOT_FOUND, EVENT_NOT_FOUND. Check the endpoint in the
generated reference for its exact code, and see Errors
for the envelope. The contact read is POST /v1/contacts/search: look one
address up with a { field: 'email', operator: 'equals' } filter.
Canonical Iteration Loop
This is the standard cursor pattern. The contact read is aPOST with
a JSON body, so the cursor rides in the body (GET lists put cursor
in the query instead):
SDK Pagination (TypeScript)
The official@brew.new/sdk returns the raw { data, pagination } shape. Pass the cursor back on the next call:
brew.contacts.search → brew.automations.runs.list with the same shape (runs use a GET list, so its filters are query params).
Filter Combinations
POST /v1/contacts/search takes search + sort + filter in one JSON body:
GET /v1/automations/runs supports time-range and status filters:
Cursor Semantics
- Opaque. Cursors are server-generated tokens. Don’t parse them; don’t synthesize them. The format may change between releases.
- Stable within a page. A cursor returned on page N points to “the next batch of rows that existed when N was rendered”. New rows inserted concurrently may show up; deleted rows may be skipped. This is fine for analytics / bulk export; if you need strict snapshot reads, freeze a time bound with
?from=&to=. - 24-hour TTL. Cursors don’t expire on a strict clock today, but treat them as if they’re good for ~24h, and re-start with no cursor if a job pauses overnight.
See Also
- Rate limits: a tight pagination loop can burn through
100/minquickly; consider parallelizing across keys or honoringX-RateLimit-Remaining. - Batch operations: for writing lots of rows fast (
POST /v1/contactsaccepts up to 1000 rows per request). - Errors:
404on a get-one lookup;400 INVALID_REQUESTon bad cursors.
Need Help?
Our team is ready to support you at every step of your journey with Brew. Choose the option that works best for you:- Self-Service Tools
- Talk to Our Team
Search Documentation
Type in the “Ask any question” search bar at the top left to instantly find relevant documentation pages.
ChatGPT/Claude Integration
Click “Open in ChatGPT” at the top right of any page to explore it further with ChatGPT or Claude.