Pagination

Cursor-based pagination across every list endpoint

Every list endpoint in the Servicebay API uses cursor-based pagination. You request a page size, receive that many items plus an opaque cursor, and pass the cursor back to fetch the next page.

Cursors are stable: a cursor returned today will still point to the same position tomorrow, even if items are added or removed in between.

Query parameters

ParameterTypeDefaultDescription
limitinteger50Maximum items per page (max: 100)
startAfterstringCursor — pass nextCursor from the previous response

Response format

{
  "success": true,
  "data": {
    "customers": [
      /* ... */
    ],
    "pagination": {
      "limit": 50,
      "hasMore": true,
      "nextCursor": "abc123xyz"
    }
  }
}
FieldDescription
limitNumber of items requested
hasMoreWhether more items exist after this page
nextCursorID to pass as startAfter in the next request

Fetching all pages

async function getAllCustomers(orgId, apiKey) {
  const all = [];
  let cursor = null;

  do {
    const url = new URL(
      `https://developer.servicebay.io/api/v1/organisations/${orgId}/customers`
    );
    url.searchParams.set("limit", "100");
    if (cursor) url.searchParams.set("startAfter", cursor);

    const res = await fetch(url, { headers: { "X-API-Key": apiKey } });
    const { data } = await res.json();

    all.push(...data.customers);
    cursor = data.pagination.hasMore ? data.pagination.nextCursor : null;
  } while (cursor);

  return all;
}
import requests

def get_all_customers(org_id, api_key):
    all_customers = []
    cursor = None

    while True:
        params = {"limit": 100}
        if cursor:
            params["startAfter"] = cursor

        res = requests.get(
            f"https://developer.servicebay.io/api/v1/organisations/{org_id}/customers",
            headers={"X-API-Key": api_key},
            params=params,
        )
        data = res.json()["data"]
        all_customers.extend(data["customers"])

        if not data["pagination"]["hasMore"]:
            break
        cursor = data["pagination"]["nextCursor"]

    return all_customers

Best practices

  • Use page sizes of 25–100. Smaller pages waste round-trips, larger pages risk timeouts on busy organisations.
  • Store the cursor if your UI lets users navigate back to a previous page.
  • Show a loading state between pages so users know more data is coming.
  • Cache aggressively for read-mostly data — pagination cursors are cheap to compare.

On this page