Endpoints that return more than one record are paginated with a cursor. The mechanism is the same across the Veridion APIs, so a client written once works everywhere.
Request parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page_size | integer, 1 to 200 | 100 | How many records to return per page. |
cursor | string, up to 1024 characters | N/A | The next_cursor value from a previous response. Omit it on the first call. |
max_results | integer, 1 to 10000 | N/A | An optional cap on the total number of records returned across all pages. Takes precedence over page_size. |
A cursor is bound to the request that produced it. Reuse it as is, and do not change the other parameters of the query while paging through it.
Response fields
| Field | Description |
|---|---|
result | The records in this page. |
next_cursor | The cursor to send on the next request, or null when there is nothing further to retrieve. |
has_more | Whether another request will retrieve more data. |
result_count | The total number of records in the result set. |
The one rule: stop when next_cursor is null
next_cursor is nullnext_cursor tells you whether to keep going. has_more tells you whether to keep going immediately.
This distinction matters because not every result set is finished when you start reading it. Most endpoints query data that already exists, and for those the two fields always agree. Some endpoints begin returning records while the rest are still being produced, and for those the set can be temporarily drained without being complete. This behavior will be documented for each endpoint individually.
A client that terminates on next_cursor == null works correctly in both cases. A client that terminates on has_more == false will stop early against an endpoint that is still producing.
has_more: truewith anullcursor cannot occurThe combination is impossible by construction, so there is no ambiguous state to handle.
Paginating a complete result set
For most endpoints the full result set exists before the first response is sent. Paging is a simple loop, and has_more mirrors next_cursor.
cursor = null // omit on the first call
loop:
page = GET /<endpoint>?cursor=<cursor>&page_size=<n>
consume(page.result)
if page.next_cursor == null:
break
cursor = page.next_cursor
Paginating a result set that is still being produced
Some endpoints return records as they become available rather than waiting for the whole set. These responses carry an additional status field, and the result set can grow between your requests.
status is a display label. It describes what the producer is doing, and it never needs to drive control flow.
status | has_more | next_cursor | What the client does |
|---|---|---|---|
processing | true | present | Fetch the next page immediately. |
processing | false | present | Nothing available right now. Wait, then re-request with the same cursor. |
complete | true | present | Fetch the next page immediately. |
complete | false | null | Stop. |
The second row is the state that does not exist for a complete result set: the producer is still working, and there is nothing to hand you yet. Send the same cursor again after a delay and later records will arrive under it.
cursor = null // omit on the first call
loop:
page = GET /<endpoint>?cursor=<cursor>&page_size=<n>
consume(page.result)
if page.next_cursor == null: // done
break
cursor = page.next_cursor
if page.has_more: // more available now
continue
else: // drained, producer still running
sleep(backoff) // re-request the same cursor
continue
The cursor is used verbatim either way. The only difference between the two branches is whether you pause first.
Write the loop onceThe second loop is correct for every paginated endpoint, including those whose result sets are always complete. Against a complete set the
elsebranch is simply never reached.If you are integrating against more than one Veridion API, implementing this version once is less work than maintaining two.
Caps and totals
max_results must be sent on every request. The cap is not carried in the cursor. If you omit it when requesting a later page, the cap no longer applies and paging continues through the full result set.
has_more goes false once the cap is reached, even when further records exist.
result_count ignores the cap. It reports the size of the result set itself, so a response can read result_count: 500 with has_more: false when you asked for ten. That is correct: five hundred records exist, and you have retrieved as many as you requested.
For an endpoint that is still producing records, result_count reflects what is known at the time of the response and can increase while status is processing.
