JQL Fundamentals

Pagination

Offset/limit pagination and retrieveV2 cursor pagination.

JQL supports classic offset pagination through retrieve and keyset cursor pagination through retrieveV2.

retrieve: offset and limit

retrieve reads __meta__.offset and __meta__.limit, orders the queryset, then slices rows as offset:offset+limit. Response extras include filtered and displayed counts.

json
1{ 2 "__meta__": { 3 "schema": "model", 4 "namespace": "tickets.Ticket", 5 "intent": "retrieve", 6 "authenticationClass": "jwt", 7 "filter": { 8 "status": "open" 9 }, 10 "ordering": "-created", 11 "offset": 0, 12 "limit": 20 13 }, 14 "id": null, 15 "title": null, 16 "created": null 17}

retrieveV2: cursor pagination

retrieveV2 is a drop-in read intent for model namespaces. Without cursor, it behaves like offset/limit. With a cursor, it applies keyset filters anchored to the previous page.

json
1{ 2 "__meta__": { 3 "schema": "model", 4 "namespace": "objects.Customer", 5 "intent": "retrieveV2", 6 "authenticationClass": "jwt", 7 "ordering": [ 8 "-created", 9 "id" 10 ], 11 "limit": 25 12 }, 13 "id": null, 14 "reference": null, 15 "created": null 16}

When the page is full and ordering fields can be read, __extras__.nextCursor is an opaque base64-encoded JSON cursor. Pass it back verbatim:

json
1{ 2 "__meta__": { 3 "schema": "model", 4 "namespace": "objects.Customer", 5 "intent": "retrieveV2", 6 "authenticationClass": "jwt", 7 "ordering": [ 8 "-created", 9 "id" 10 ], 11 "limit": 25, 12 "cursor": "eyJjcmVhdGVkIjogIjIwMjYtMDctMjJUMDA6MDA6MDBaIiwgImlkIjogIjEwMSJ9" 13 }, 14 "id": null, 15 "reference": null, 16 "created": null 17}

nextCursor is null when no rows are returned, the page has fewer rows than limit, or ordering values cannot be extracted.

Ordering guidance

Always include deterministic ordering for cursor pagination. A timestamp plus id is a good pattern: ["-created", "id"]. For mutable sort fields, include a stable tiebreaker.

See filters and queries and /developer/data-hooks.