Pagination

How to page through OpenRelay list endpoints with cursors.

List endpoints that can return many items are cursor-paginated. You request a page, and the response tells you how to fetch the next one.

Request

Pass two optional query parameters:

  • limit — maximum number of items to return for this page.
  • cursor — an opaque pointer to the next page, taken from the previous response.
curl "https://api.openrelay.inc/v1/orgs/$ORG_ID/clusters?limit=50" \
  -H "Authorization: Bearer $OPENRELAY_API_KEY"

Response

A page returns an items array and, when more results exist, a nextCursor:

{
  "items": [
    { "id": "cl_…", "name": "prod-llama", "status": "running" }
  ],
  "nextCursor": "eyJpZCI6…"
}

When nextCursor is absent (or empty), you've reached the last page.

Iterating all pages

Pass the previous nextCursor as the next request's cursor until it's gone:

cursor=""
while :; do
  resp=$(curl -fsS \
    "https://api.openrelay.inc/v1/orgs/$ORG_ID/clusters?limit=100&cursor=$cursor" \
    -H "Authorization: Bearer $OPENRELAY_API_KEY")

  echo "$resp" | jq -c '.items[]'

  cursor=$(echo "$resp" | jq -r '.nextCursor // empty')
  [ -z "$cursor" ] && break
done
TypeScript
async function* listClusters(orgId: string) {
  let cursor: string | undefined;
  do {
    const url = new URL(`https://api.openrelay.inc/v1/orgs/${orgId}/clusters`);
    url.searchParams.set('limit', '100');
    if (cursor) url.searchParams.set('cursor', cursor);

    const res = await fetch(url, {
      headers: { Authorization: `Bearer ${process.env.OPENRELAY_API_KEY}` },
    });
    const page = await res.json();
    yield* page.items;
    cursor = page.nextCursor || undefined;
  } while (cursor);
}

Treat cursors as opaque

A cursor encodes our position in the result set — don't parse, modify, or construct one. Always use the exact nextCursor value from the previous response.

On this page