Pagination
QRForge API endpoints that return collections (e.g., List Projects, List QR Codes) use a cursor‑based pagination model designed for scalability and enterprise‑grade performance.
This document explains how pagination works, how to retrieve the next page, and how to handle edge cases.
Overview
QRForge uses cursor-based pagination, not offset-based pagination.
Cursor pagination is more stable and performant at scale because it avoids skipping records and remains efficient on large Firestore datasets.
Each paginated endpoint returns:
items: Array of resultsnext_page_token: Opaque string ornull- Other metadata depending on the endpoint
If next_page_token is present in the response, its value must be passed back into the API — as the page_token request parameter — to retrieve the next page.
Request Parameters
page_size (optional)
- Defines how many items to return per page.
- Integer between 1 and 100.
- If omitted or non-numeric, the API defaults to 20 items.
- Values above 100 are silently capped at 100.
An out-of-range page_size is never rejected with an error — it's always normalized to a safe value instead:
page_size=1→ returns exactly one item (if available)page_size=0or a negative value → normalized up (to 1 on some endpoints, or back to the default of 20 on others — never an error either way)
page_token (optional)
- Used to continue fetching results from the previous page.
- Set this to the
next_page_tokenvalue returned in the previous response. - Opaque value generated by the backend.
- Must never be modified or decoded by the client.
Example call:
GET /v1/qr-codes?page_size=50&page_token=eyJjIjoxMjM0NTY3ODkwfQ
Response Structure
All paginated responses follow this pattern:
{
"ok": true,
"version": "2025-11-14-v1",
"request_id": "UUID",
"items": [
{ /* item */ }
],
"next_page_token": "opaque-string-or-null"
}
Example Flow
1. First request (no token)
GET /v1/projects?page_size=2
Response:
{
"ok": true,
"items": [
{ "project_id": "projA", ... },
{ "project_id": "projB", ... }
],
"next_page_token": "eyJjIjoxMjM0NTY3ODkwfQ"
}
2. Fetch next page
GET /v1/projects?page_size=2&page_token=eyJjIjoxMjM0NTY3ODkwfQ
Response:
{
"ok": true,
"items": [
{ "project_id": "projC", ... }
],
"next_page_token": null
}
At this point:
next_page_tokenisnull, so no further pages exist.
When next_page_token Is null
A null token always means:
- You have reached the end of the dataset
- No additional requests are needed
Error Handling
The pagination parameters themselves degrade gracefully rather than erroring:
- An out-of-range or non-numeric
page_sizeis normalized (see above) — it never causes aninvalid_requesterror. - A corrupted, expired, or malformed
page_tokenis silently ignored — the request simply restarts from the first page instead of erroring. Don't rely on a bad token producing a visible failure; if you need to detect this, compare the returneditemsagainst what you expect for "page 2+".
The usual endpoint-level errors (missing/invalid API key, rate limits, plan entitlements) still apply on top of this — see the Error Reference for the full catalog.
Best Practices
Always check for next_page_token
Do not assume the number of pages based on item count.
Do not reuse tokens indefinitely
Tokens should only be used for a single pagination chain.
Do not attempt to interpret the token
It is intentionally opaque and may change formats in the future.
For bulk or export use cases
Use the Exports API when available (coming in v2), not pagination loops.
Summary
Pagination in QRForge is:
- Cursor-based
- Efficient at scale
- Consistent across endpoints
- Simple for clients to consume
Endpoints supporting pagination include:
/v1/projects/v1/qr-codes
More endpoints will adopt this structure as the API expands.