Skip to main content
Conduit list endpoints paginate with opaque cursors. You request a page, read meta.pagination, and follow next_cursor until has_more is false. Cursors are stable for the result set you started, so paging stays consistent even as new observations arrive. This page covers the query parameters, the meta.pagination block, and a complete loop in cURL and TypeScript.

Query parameters

All list endpoints accept the same paging controls.
limit
integer
default:"100"
Page size, from 1 to 500. Defaults to 100. Larger pages mean fewer round trips; smaller pages mean lower latency per request.
cursor
string
An opaque cursor that marks where the next page begins. Omit it on your first request. On every subsequent request, pass the next_cursor value from the previous response. Do not construct or parse cursor values: treat them as opaque tokens.
sort
string
The field to sort by. The set of sortable fields depends on the endpoint. Consult the OpenAPI spec for what each endpoint supports.
order
string
default:"asc"
Sort direction: asc or desc. Defaults to asc.
Unknown query parameters are rejected, not ignored. A misspelled parameter returns bad_request. See Errors.

The pagination block

List responses carry the cursor state under meta.pagination. (Item responses do not paginate and omit this block.)
meta.pagination.limit
integer
The page size applied to this request.
meta.pagination.cursor
string | null
The cursor you supplied for this page, or null on the first page.
meta.pagination.next_cursor
string | null
The cursor to pass on your next request. null when there are no more pages.
meta.pagination.has_more
boolean
true when more pages remain. Loop while this is true.
First page response (truncated)
{
  "data": [ /* up to `limit` observations */ ],
  "meta": {
    "request_id": "8f1c2e90-7a4b-4c3d-9e21-2b6f0a1c4d55",
    "requestId": "8f1c2e90-7a4b-4c3d-9e21-2b6f0a1c4d55",
    "api_version": "v1",
    "pagination": {
      "limit": 100,
      "cursor": null,
      "next_cursor": "eyJvIjoxMDB9",
      "has_more": true
    }
  },
  "requestId": "8f1c2e90-7a4b-4c3d-9e21-2b6f0a1c4d55"
}

The loop

The rule is one line: while meta.pagination.has_more is true, repeat the request with cursor set to the previous next_cursor. Stop when has_more is false (equivalently, when next_cursor is null).
1

Request the first page

Call the endpoint with your filters and an optional limit. Do not send cursor.
2

Process the page

Read the items from data.
3

Check has_more

If meta.pagination.has_more is false, you are done.
4

Advance the cursor

Otherwise, request again with cursor set to meta.pagination.next_cursor, keeping the same filters, and return to step 2.
# Walk every page of USA CPI observations, 500 rows at a time.
BASE="https://data.quantoraresearch.com/v1/public/observations"
QUERY="country=USA&indicator=cpi_inflation_yoy&limit=500"
CURSOR=""

while : ; do
  if [ -z "$CURSOR" ]; then
    URL="$BASE?$QUERY"
  else
    URL="$BASE?$QUERY&cursor=$CURSOR"
  fi

  RESP=$(curl -s -H "x-api-key: $CONDUIT_API_KEY" "$URL")

  echo "$RESP" | jq '.data[]'   # process the page

  HAS_MORE=$(echo "$RESP" | jq -r '.meta.pagination.has_more')
  if [ "$HAS_MORE" != "true" ]; then
    break
  fi
  CURSOR=$(echo "$RESP" | jq -r '.meta.pagination.next_cursor')
done
The official TypeScript SDK @conduit/client handles the cursor loop for you. Async iteration walks every page behind the scenes, so the manual loop above is only needed when you call the API directly.

Notes

  • Cursors are opaque. Their internal format is not part of the contract and may change. Read them from next_cursor and pass them back verbatim.
  • Keep your filters identical across pages. Changing country, indicator, sort, or order mid-walk invalidates the cursor.
  • A page may contain fewer than limit items and still have has_more: true. Always trust has_more, never the item count, to decide whether to continue.

Response envelope

Where meta.pagination lives within the shared envelope.