BrightshoalDocsOpen console
MenuPagination

API basics

Pagination

Which lists come back in pages, how to walk them with a cursor, and which return everything at once.

Lists that can grow without bound (calls, leads, conversations, audit entries) come back one page at a time, newest first. You ask for the next page with the cursor the previous page gave you.

The shape of a page

Response
{
  "data": [{ "id": "call_9e1d..." }, { "id": "call_4b7a..." }],
  "next_cursor": "eyJ0IjoiMjAyNi0xMC0yOFQwOToyOTo1OC4xMjM0NTZaIiwiaSI6ImNhbGxfNGI3YS4uLiJ9",
  "has_more": true
}
FieldMeaning
dataThis page, newest first.
has_moretrue while there are older rows.
next_cursorSend it as cursor to get the next page; null on the last page. Treat it as opaque.

Two query parameters drive it:

ParameterMeaning
limitRows per page. Defaults to 50. Values above the maximum are lowered to it, not refused.
cursorThe next_cursor from the page before. Leave it out for the first page.

Keep every other filter (from, to, assistant_id, status, and so on) the same from page to page; the cursor only says where the last page stopped.

Which endpoints page

EndpointMax limitNotes
GET/api/calls200Filters: assistant_id, status, call_type, from, to, q.
GET/api/leads200Filters: project_id, from, to.
GET/api/conversations200Also sorts: sort=created_at or message_count, dir=desc or asc. Add include_total=true for a total count.
GET/api/audit-log200
GET/api/chat-analytics/failures100
GET/api/chat-analytics/incidents100

Everything else returns the whole list in data with no cursor: assistants, projects, phone numbers, publishable keys, webhooks, knowledge bases, alerts and the rest. Some are filtered by default: publishable keys list site keys unless you pass kind=test or kind=all, and an assistant's version history returns its latest 100. Webhook deliveries are the exception in between: GET/api/webhooks/{id}/deliveries returns the newest 100 attempts and has no further pages.

Walk every page

async function* allCalls(params = {}) {
  let cursor
  do {
    const qs = new URLSearchParams({ ...params, limit: '200', ...(cursor ? { cursor } : {}) })
    const res = await fetch(`https://api.myleadsfactory.tech/api/calls?${qs}`, {
      headers: { Authorization: `Bearer ${process.env.MLF_API_KEY}` },
    })
    if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`)
    const page = await res.json()
    yield* page.data
    cursor = page.has_more ? page.next_cursor : undefined
  } while (cursor)
}

for await (const call of allCalls({ from: '2026-10-01T00:00:00Z' })) {
  console.log(call.id, call.status)
}

Rows that arrive while you page

Pages are ordered by creation time and id, so a row created after you started is never slipped into a later page: it is newer than your first page, and the next walk from the top picks it up. Rows created in the same millisecond keep their order too.

Stuck on pagination?