Pagination
Every list endpoint pages via opaque cursor tokens. Walk a result set by passing back the next_cursor you receive on the previous page.
The cursor contract
One pattern across every list endpoint.
List endpoints (/v2/tickers, /v2/scan, /v2/news, /v2/series, /v2/events, /v2/tickers/{ticker}/bars/{interval}, /v2/signals/{signal}, /v2/signals/.../events, /v2/universes, /v2/webhooks, /v2/webhooks/{id}/deliveries) return a next_cursor alongside the data. Pass it back to get the next page — as ?cursor= in the query string on GET endpoints, or in the JSON body alongside the rest of the parameters on POST endpoints (POST /v2/scan, POST /v2/news). When there’s no more data, next_cursor is null.
Treat cursors as opaque
Don’t parse them. Don’t construct them. Don’t cache them.
The server bakes the resume position into each token. If you need to change the filter, start a new walk.
One documented exception: /v2/tickers/{ticker}/bars uses the oldest returned bar’s epoch-ms timestamp as its cursor (cursor and before are interchangeable there). It’s readable, but treat it the same way — pass back what you received.
Cursors and filters
Two models, stated per endpoint.
Filter-resend (news, analyst, the tickers list, 1q history, the crypto list): the cursor carries only the resume position — send the same filter params on every page.
Filter-pinning (/v2/events): the cursor pins the original filters as well. Resending a matching param is fine; a conflicting one is a 400 naming it. Long q strings and big ticker lists aren’t in the token — resend those with the cursor.
Page size
Pass ?limit=; each endpoint documents its own maximum.
Pass ?limit= to change page size. Most read endpoints cap at 1,000 rows per page (series and the history endpoints default to 252 — one trading year); each endpoint page states its default and maximum. Bulk-fetch endpoints (/v2/tickers?tickers=…) have their own limits documented on the endpoint page.