Get started
Pagination
Lists are paginated with opaque cursors: stable while data changes, and fast at any depth.
How it works
List endpoints return a page of items and a nextCursor. Pass that cursor back as
cursor (in the query string, or the body for POST …/search) to get the next
page. When
nextCursor is null, you’ve reached the end.
-
limitsets the page size: 1 to 100, default 25 (conversation parts default to 50). -
The first page of
/contacts,/companiesand/articlesalso includestotal, the number of matches. - Cursors are opaque and tied to the list’s order and filters: send the same parameters with each cursor, and don’t build or edit cursors yourself.
-
Small collections — tags, ticket types, teams, teammates, data attributes, segments, collections — come
back complete, with
nextCursor: null.
{ "items": [ { "object": "contact", "id": "0199c512-6a7b-7c8d-9e0f-1a2b3c4d5e6f", "role": "user", "externalId": "usr_48213", "email": "[email protected]", "phone": "+49 30 1234567", "name": "Lena Fischer", "avatarUrl": null, "ownerId": "0199a8f2-2d3e-7f4a-9b5c-6d7e8f9a0b1c", "location": { "city": "Berlin", "region": "Berlin", "country": "Germany", "countryCode": "DE", "timezone": "Europe/Berlin" }, "language": "de", "browser": "Chrome", "os": "macOS", "lastSeenAt": "2026-10-02T13:58:20.000Z", "lastContactedAt": "2026-10-02T14:11:08.000Z", "lastRepliedAt": "2026-10-02T14:05:31.000Z", "signedUpAt": "2025-03-08T10:00:00.000Z", "sessionCount": 214, "unsubscribedFromEmails": false, "blocked": false, "customAttributes": { "plan": "business", "seats": 12, "mrr": 1490 }, "tags": [ { "id": "0199a8f3-5d6e-7f7a-8b8c-9d0e1f2a3b4c", "name": "VIP" } ], "companies": [ { "id": "0199c514-2b3c-7d4e-9f5a-6b7c8d9e0f1a", "name": "Northwind Analytics" } ], "createdAt": "2026-09-14T09:12:44.000Z", "updatedAt": "2026-10-02T16:40:03.000Z" } ], "nextCursor": "WyIyMDI2LTEwLTAyVDE0OjA1OjMxLjAwMFoiLCIwMTk5YzUyMC03ZThmIl0", "total": 1284} Fetching every page
async function* listAll(path, params = {}) { let cursor = null do { const query = new URLSearchParams({ ...params, limit: "100", ...(cursor ? { cursor } : {}) }) const res = await fetch(`https://api.rabbitblaze.com/v1${path}?${query}`, { headers: { Authorization: `Bearer ${process.env.RABBITBLAZE_API_KEY}` }, }) if (!res.ok) throw new Error((await res.json()).error.message) const page = await res.json() yield* page.items cursor = page.nextCursor } while (cursor)} for await (const contact of listAll("/contacts", { role: "user" })) { console.log(contact.email)} import osimport requests session = requests.Session()session.headers["Authorization"] = f"Bearer {os.environ['RABBITBLAZE_API_KEY']}" def list_all(path, **params): cursor = None while True: query = {**params, "limit": 100, **({"cursor": cursor} if cursor else {})} res = session.get(f"https://api.rabbitblaze.com/v1{path}", params=query) res.raise_for_status() page = res.json() yield from page["items"] cursor = page["nextCursor"] if not cursor: break for contact in list_all("/contacts", role="user"): print(contact["email"]) Syncing changes
To keep a copy of conversations up to date, list them with order=updated and
updatedAfter set to your last sync time, or — better — subscribe to webhooks and only fetch what changed.