Pagination

Hooksbase uses opaque cursor pagination for list endpoints. You ask for one page at a time, receive a nextCursor when more results exist, and send that cursor back with the exact same filter set to fetch the next page.

Cursor model

Pagination rules are consistent across the supported list routes:

  • limit defaults to 20
  • limit is clamped to 1..100
  • malformed non-integer limit values return 400
  • cursors are opaque; do not parse or construct them yourself
  • foreign or malformed cursors return 400
  • cursors are scoped to the exact active filter set

Example request:

Request one page

curl -G https://api.hooksbase.com/v1/deliveries \
  -H "Authorization: Bearer swk_..." \
  -d webhookId=wh_... \
  -d limit=20

Example response shape:

Paged list response

{
  "items": [
    { "id": "del_...", "status": "succeeded" }
  ],
  "nextCursor": "eyJ..."
}

When nextCursor is present, pass it back as the cursor query parameter on the next request (keeping every other filter identical). When it is null or absent, you have reached the end.

Supported endpoints

These Public API routes use cursor pagination:

  • GET /v1/webhooks
  • GET /v1/project/api-keys
  • GET /v1/project/audit-logs
  • GET /v1/deliveries
  • GET /v1/webhooks/{id}/deliveries
  • GET /v1/deliveries/{id}/replay-jobs
  • GET /v1/dlq
  • GET /v1/dlq/export
  • GET /v1/webhooks/{id}/schedules
  • operator alerting list and dispatch-history routes under /v1/project

Some cursors are scoped even more tightly:

  • webhook cursors include the authenticated project and webhook status filter
  • project delivery cursors include the full filter set
  • replay-job cursors are scoped to one source delivery
  • DLQ cursors are scoped to the active DLQ filter set
  • DLQ export accepts cursor pagination but caps each export page at 20 rows

Using the SDK helpers

The TypeScript SDK includes paginateCursor() and takePages() helpers when you want to consume multiple server pages without hand-rolling the loop.

Iterate deliveries one page at a time

import { createHooksbaseClient, paginateCursor, takePages } from '@hooksbase/sdk'

const client = createHooksbaseClient({ apiKey: process.env.HOOKSBASE_API_KEY })

const iterator = paginateCursor((cursor) =>
  client.deliveries.list({
    webhookId: 'wh_123',
    limit: 20,
    cursor: cursor ?? undefined,
  }),
)

for await (const delivery of iterator) {
  console.log(delivery.id, delivery.status)
}

// Or stop after the first N items:
const first100 = await takePages(iterator, 100)

Each callback receives the latest cursor (null on the first call) and returns the raw { items, nextCursor } response. The helper keeps requesting pages until nextCursor is null or absent.

Common mistakes

  • Reusing a cursor with a different filter set.
  • Assuming cursor pagination supports arbitrary jump-to-page behavior.
  • Treating the cursor as stable forever. Always read and use the latest nextCursor from the response you just received.

Was this page helpful?