Skip to main content
The API uses cursor-based pagination for all list endpoints. This approach is safe for incremental syncing and handles data changes between pages gracefully.

How it works

Every list response includes a meta object:
{
  "data": [...],
  "meta": {
    "next_cursor": "eyJpZCI6NDUsInVwZGF0ZWRfYXQiOiIyMDI2LTA0LTE1VDA5OjAwOjAwWiJ9",
    "limit": 25
  }
}
  • next_cursor is an opaque string. Pass it as the cursor query parameter to get the next page.
  • When next_cursor is null, you’ve reached the last page.

Paging through results

# First page
curl "https://prod-api.civicmarketplace.com/v1/contracts?limit=25" \
  -H "Authorization: Bearer cmp_live_YOUR_KEY"

# Next page (use next_cursor from previous response)
curl "https://prod-api.civicmarketplace.com/v1/contracts?limit=25&cursor=eyJpZCI6NDV9" \
  -H "Authorization: Bearer cmp_live_YOUR_KEY"

Page size

Control the number of results per page with the limit parameter:
ParameterDefaultMinMax
limit251100

Full pagination example

async function fetchAllContracts(apiKey) {
  const contracts = [];
  let cursor = null;

  do {
    const url = new URL("https://prod-api.civicmarketplace.com/v1/contracts");
    url.searchParams.set("limit", "100");
    if (cursor) url.searchParams.set("cursor", cursor);

    const response = await fetch(url, {
      headers: { Authorization: `Bearer ${apiKey}` },
    });
    const page = await response.json();

    contracts.push(...page.data);
    cursor = page.meta.next_cursor;
  } while (cursor);

  return contracts;
}
Combine pagination with updated_since to efficiently sync only changed records. See the Syncing Data guide.