Pagination
Page through search results with cursor pagination (default) or offset pagination, and choose the right mode for your use case.
Search endpoints return one page of records per request. Two pagination modes are available and you choose between them with a query parameter: send cursor (or nothing) for cursor pagination, or send offset for offset pagination. The two are mutually exclusive — a request containing both is rejected with 400.
Parameters
| Parameter | Type | Range | Default | Applies to |
|---|---|---|---|---|
limit | integer | 1–100 | 50 | Both modes |
cursor | string | ≤ 200 characters, opaque | first page | Cursor mode |
offset | integer | 0–10000 | 0 | Offset mode |
Out-of-range values are rejected with 400, not clamped. Count endpoints take no pagination parameters.
Which mode to use
| Cursor (default) | Offset | |
|---|---|---|
| Request | ?cursor=<token>, or no pagination parameter | ?offset=<n> |
page object in response | { limit, nextCursor, hasMore } | { limit, offset, total } |
| Total match count | Not included — call the count endpoint once | Included in every response |
| Ordering | Fixed internal order. options.sortFields is ignored | Sortable by headcount or revenue via options.sortFields |
| Depth | Up to 100,000 records per journey | offset ≤ 10,000 |
| Jump to page n | No | Yes |
| Cost per page | Lower — no total is recomputed | Higher — the total is recomputed on every page |
Use cursor pagination for anything that walks a result set — exports, CRM syncs, infinite scroll. It does not slow down as you go deeper and it will not skip or duplicate records the way a shifting offset can.
Use offset pagination when you need numbered pages or a ranked list (for example, the 20 largest companies by revenue). Because every offset response recomputes the total, a broad filter pays for a count on every page; if you will page more than a few times, use a cursor plus one call to the count endpoint instead.
Cursor pagination
Lifecycle
- First page — send the filter with no
cursor.limitis optional. - Next pages — copy
page.nextCursorfrom the response into thecursorquery parameter and send the identical request body again. - Stop — when
page.hasMoreisfalseandpage.nextCursorisnull.
# First page
curl --request POST \
--url 'https://api.cognism.com/companies/filter?limit=50' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'Content-Type: application/json' \
--data '{ "company": { "industry": { "include": ["Software"] } } }'{
"page": {
"limit": 50,
"hasMore": true,
"nextCursor": "eyJ2IjoxLCJzIjoiLTkwOTIyNzYwNTA4NjMyNDY5NzciLCJoIjoiNWI1ODlhY2IiLCJuIjo1MH0"
},
"data": [ "…50 company records…" ]
}# Next page — same body, cursor from the previous response
curl --request POST \
--url 'https://api.cognism.com/companies/filter?limit=50&cursor=eyJ2IjoxLCJzIjoiLTkwOTIyNzYwNTA4NjMyNDY5NzciLCJoIjoiNWI1ODlhY2IiLCJuIjo1MH0' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'Content-Type: application/json' \
--data '{ "company": { "industry": { "include": ["Software"] } } }'Rules
- The cursor is opaque. It is a base64url token whose contents are an implementation detail and whose format is versioned. Do not parse it, modify it, construct one by hand, or store it long term.
- The cursor is bound to your filter. The server fingerprints the request body when it issues a cursor and checks that fingerprint when the cursor comes back. Changing the filter mid-journey returns
400 cursor_filter_mismatchrather than silently mixing result sets. To search differently, start a new journey from the first page. - Consistency is bounded, not snapshot. Results are paged from a live index. Records that change between page requests may be skipped, duplicated or reordered.
options.sortFieldsis ignored in cursor mode. If you need a sorted result, use offset pagination.
Offset pagination
Send offset to request a specific window of the result set. Each response includes the total number of matching records.
curl --request POST \
--url 'https://api.cognism.com/companies/filter?offset=0&limit=20' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"company": { "industry": { "include": ["Software"] } },
"options": { "sortFields": [ { "field": "revenue", "direction": "DESC" } ] }
}'{
"page": { "limit": 20, "offset": 0, "total": 48213 },
"data": [ "…20 company records, largest revenue first…" ]
}options.sortFields accepts headcount and revenue only, each with direction ASC or DESC. Sorting is applied only in offset mode; the same body sent with a cursor returns results in the fixed internal order.
Pagination errors
| HTTP | error | When | What to do |
|---|---|---|---|
| 400 | (validation) | cursor and offset sent together, or limit/offset out of range. | Fix the request. |
| 400 | invalid_cursor | The cursor is malformed or from an unsupported version. | Restart the journey from the first page. |
| 400 | cursor_filter_mismatch | The request body changed since the cursor was issued. | Send the original body, or start a new journey. |
| 422 | pagination_depth_exceeded | The cursor journey has passed 100,000 records. | Narrow the filter and start again. |
None of these apply to the count endpoints. See Errors for the error envelope.
Updated 2 days ago

