Skip to main content
JTL’s APIs return large collections in pages rather than all at once. Any endpoint that returns a list of items (products, invoices, customers, orders, etc.) includes pagination metadata so you can navigate through the results. The JTL Platform uses two pagination styles depending on the API surface:

Page-based Pagination (REST)

The REST API uses page-based pagination. Each response includes the current page of items plus metadata telling you the total number of items, how many pages exist, and whether there are more pages to fetch.
Examples below are in TypeScript. The patterns applies to any language with an HTTP client.

Making a Paginated Request

Response Structure

Every paginated REST response follows this structure:

Metadata Fields

Requesting a Specific Page

Pass pagination parameters in the query string:

Fetching the Next Page

Use hasNextPage and nextPageNumber to decide whether more results exist:

Fetching All Pages

To retrieve every item across all pages, loop until hasNextPage is false:

Cursor-based Pagination (GraphQL)

The GraphQL API uses cursor-based pagination. Instead of page numbers, you use an opaque cursor string to request the next set of results. This is more reliable for large, frequently changing datasets because new or deleted records don’t shift the page boundaries.

Making a Paginated Request

Pass first (page size) and optionally after (cursor) as query variables:
What this does: Fetches the first 20 items. The pageInfo object tells you whether more pages exist and provides the cursor for the next page.

Response Structure

Metadata Fields

Fetching the Next Page

Pass the endCursor from the previous response as the after variable on the next request, and stop when hasNextPage is false:
What this does: Loops through pages by passing the endCursor from each response as the after variable in the next request. Stops when hasNextPage is false.

Best Practices

Use the smallest page size you need. Use smaller page sizes for UI-driven fetching (10-20 items). Use larger sizes only for background sync or batch jobs (50-100 items). Don’t rely on total counts for logic. Both totalItems (REST) and totalCount (GraphQL) can change between requests as data is created or deleted. Use them for display only, not for control flow. Handle empty pages gracefully. If a page has no items (e.g., records were deleted between requests), the items array will be empty. Don’t treat this as an error:
Respect rate limits when fetching all pages. Large paginated fetches can hit rate limits. Add a delay or use exponential backoff between requests.
Avoid parallel page fetches. Fetch pages sequentially unless you control rate limits and ordering. Parallel fetches can cause ordering issues and increase the risk of rate limiting. Choose the right pagination style for your use case. If you’re calling REST endpoints (invoices, payments), use page-based. If you’re querying ERP data through GraphQL (items, categories, customers), use cursor-based. Don’t mix them up.

Quick Reference


What’s Next?

Rate Limiting

Understand request quotas, especially important when fetching many pages.

Error Handling

Handle errors that may occur during paginated fetches.

Using Platform APIs

Full guide to querying the GraphQL API with filtering, sorting, and pagination.

Webhooks

Instead of polling pages for changes, use webhooks to get notified in real time.