Page through collections

Every collection endpoint answers with the same envelope and pages the same way. This guide walks a collection of documents from the first page to the last — two requests in total.

Before you begin

  • A few documents to page through. The example assumes three.

Step 1: Read the first page

Ask for the first page, two items at a time:

GET /documents?limit=2
Authorization: Bearer YOUR_API_KEY
HTTP/2 200

{
    "pagination": {
        "limit": 2,
        "nextCursor": "e3b7a92c15d84f60c7a2b95e1d3f48a6b90c4e27d5f18a3c6e9b02d47f5a1c38",
        "offset": 0
    },
    "total": 3,
    ...
}

The envelope is always the same three parts: results with the items (omitted here — they are full document objects), total with the overall count, and pagination describing where you are.

That leaves two ways to move through a collection, and this response offers both. offset and limit jump straight to a page, which suits shallow access — a page of results in your own interface, for instance. Walking the whole collection is the cursor's job: nextCursor is issued while you page from the start of the results — on the first page and then on every cursor page. Jumping in with an offset of your own leaves the walk behind, so those pages carry no cursor at all; pick one of the two approaches per traversal rather than mixing them.

A cursor is issued only for a page that came back full, which is how the walk ends: as soon as a page holds fewer items than the limit you asked for, nextCursor is null. A collection whose size is an exact multiple of the limit therefore hands you one more cursor and one final, empty page — so drive the loop off nextCursor rather than off the number of items you got.

Step 2: Follow the cursor

Pass the cursor back to get the next page:

GET /documents?cursor=e3b7a92c15d84f60c7a2b95e1d3f48a6b90c4e27d5f18a3c6e9b02d47f5a1c38
Authorization: Bearer YOUR_API_KEY
HTTP/2 200

{
    "pagination": {
        "limit": 2,
        "nextCursor": null,
        "offset": 2
    },
    "total": 3,
    ...
}

One document remains and nextCursor is null — you have reached the end. The offset field shows your position as a progress indicator.

Important

A cursor must be the only parameter of the request — the filters are remembered from the first page — and it expires after a period of inactivity. Continuous paging is fine; a long pause means starting over.

Endpoints that always return their complete list in one response carry pagination: null instead. There is nothing to follow there, and total is the number of items you received.

Complete example

Collecting a whole collection, page by page, as a Node.js script. Error handling is minimal for brevity — in production, inspect the error envelope of non-2xx responses.

JavaScript
const BASE_URL = "https://sandbox.circularo.com/api/v1/public"; // your instance's base URL
const API_KEY = "YOUR_API_KEY";
const AUTH_HEADER = { "Authorization": `Bearer ${API_KEY}` };

const documents = [];
let query = "limit=2&category=Contract";

do {
    const res = await fetch(`${BASE_URL}/documents?${query}`, { headers: AUTH_HEADER });
    if (!res.ok) throw new Error(`Listing failed: ${res.status}`); // error handling kept minimal for brevity

    const page = await res.json();
    documents.push(...page.results);
    console.log(`${documents.length} of ${page.total}`);

    // from here on the cursor travels alone - it already carries the filters
    query = (page.pagination.nextCursor === null) ? null : `cursor=${page.pagination.nextCursor}`;
} while (query !== null);

Next steps

  • Narrow a collection down before you page through it — Search documents.

  • Handle the errors a long walk can run into, including the rate limit — Handle errors.