SurfacedBySurfacedBy Docs
DocumentationReference

Pagination

Cursor-based pagination used across every list endpoint.

Ask an AI:Open in ChatGPTOpen in Claude

Every list endpoint in the API paginates the same way. This page is the authoritative reference for the mechanism.

Cursor-based

SurfacedBy uses opaque cursor pagination, not offset pagination. Cursors are stable across inserts: if new rows are written between page 1 and page 2, you will not see duplicates or skipped rows.

Response shape

{
  "data": [
    { "...": "item" },
    { "...": "item" }
  ],
  "next_cursor": "eyJpZCI6IjE3MjYi..."
}

When next_cursor is present, there is at least one more page. When next_cursor is null or omitted, you have reached the end.

Making a paginated call

The first request omits the cursor parameter:

curl "https://api.surfacedby.com/api/v1/ext/domains" \
  -H "X-API-Key: sk_live_..."

Subsequent requests pass the cursor returned by the previous page:

curl "https://api.surfacedby.com/api/v1/ext/domains?cursor=eyJpZCI6IjE3MjYi..." \
  -H "X-API-Key: sk_live_..."

Loop until next_cursor is null.

Rules

  • Treat cursors as opaque. Do not parse, do not decode, do not construct.
  • Do not cache cursors across sessions. Cursors are tied to the current sort state of the endpoint and may not be valid indefinitely.
  • Cursors returned from one endpoint are not meaningful on a different endpoint.

Page size

Page size is set by the endpoint, not the caller. You do not send a limit parameter. This keeps pagination predictable: every caller sees the same page size, and rate-limit budgets are easier to reason about.

If you need every record for a domain (for example, an export), loop with cursors until next_cursor is null.

Sample loop

import httpx
 
def list_all(path, headers):
    url = f"https://api.surfacedby.com/api/v1/ext{path}"
    cursor = None
    while True:
        params = {"cursor": cursor} if cursor else None
        resp = httpx.get(url, headers=headers, params=params)
        resp.raise_for_status()
        body = resp.json()
        yield from body["data"]
        cursor = body.get("next_cursor")
        if not cursor:
            return

On this page