Skip to main content
Brew list endpoints use opaque cursor pagination. Every paginated response carries a pagination: { limit, cursor?, hasMore } envelope so callers can iterate without page-counting math.

The Pagination Envelope

Where it appears (read mode):

Endpoints That Paginate

Every list endpoint accepts limit (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 read data[0]. The response is the same { data, pagination } envelope as the list: just scoped to one row. ?include= opt-ins embed the heavier detail: When the id misses, you get an empty data array (and 404 <RESOURCE>_NOT_FOUND only on the path-based write endpoints, e.g. PATCH /v1/automations/{automationId}). 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 a POST 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:
For automation runs, swap brew.contacts.searchbrew.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:
See the per-endpoint pages under Public API v1 for the full filter parameter table.

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/min quickly; consider parallelizing across keys or honoring X-RateLimit-Remaining.
  • Batch operations: for writing lots of rows fast (POST /v1/contacts accepts up to 1000 rows per request).
  • Errors: 404 on a get-one lookup; 400 INVALID_REQUEST on 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:

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 analyze documentation with ChatGPT or Claude for deeper insights.