SurfacedBySurfacedBy Docs
DocumentationReference

Pagination

Forward-only cursor pagination used by the Data API list endpoints.

Ask an AI:Open in ChatGPTOpen in Claude

Every paginated Data API list endpoint uses the same cursor scheme. The platforms list returns the whole catalog in one response, without a cursor.

Cursor-based

SurfacedBy uses forward-only cursor pagination, not offset pagination. A cursor records the sort position of the last row on the page, including the row id, so rows that share a sort value are never repeated or skipped between pages. Rows added after you fetched the first page and that sort ahead of your position are not returned in that pass; start again from the first page to see them.

Response shape

{
  "data": [
    { "...": "item" },
    { "...": "item" }
  ],
  "meta": {
    "has_more": true,
    "next_cursor": "W1tbImNyZWF0ZWRfYXQiLCIyMDI2...",
    "request_id": "req_..."
  }
}

When meta.next_cursor is a string, there is at least one more page and has_more is true. When it is null, 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_..."

Later requests pass the cursor returned by the previous page:

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

Loop until meta.next_cursor is null.

Rules

  • Treat cursors as opaque. Do not parse, modify, or construct them.
  • A cursor is only meaningful on the endpoint, and for the domain, that returned it.
  • A cursor that cannot be decoded returns 422 validation_error.
  • Pagination is forward only. To go back, start again from the first page.

Page size

Page size is fixed by the endpoint; there is no limit parameter.

EndpointPage size
List domains50
List competitors50
List opportunities50
List reports50
List scans50
List prompts100

The trend deltas endpoint (diff) uses the list envelope but always returns a single item and no cursor. Requests made with a test key return the whole sample set in one page.

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["meta"].get("next_cursor")
        if not cursor:
            return

On this page