~/qa-guides

~/qa-guides/api-pagination-testing-checklist

>_ API Pagination Testing Checklist

A practical checklist for testing paginated API collections, with worked examples of complete traversal, tied sort values, empty pages, and changing data.

APIPaginationCursorsData integrity

Published

Short answer

An API pagination testing checklist verifies how a list endpoint divides results into pages, how a client requests the next page, and whether traversing the collection returns the expected records in the expected order. It covers page-size boundaries, page and offset parameters, cursors, filters, continuation metadata, empty results, and changes between requests.

The central check is a complete traversal of a known dataset. Compare returned record IDs with an independently prepared expected set, identify omissions and duplicates, and confirm that the client stops at the endpoint's documented end signal.

Use this guide when changing a list endpoint or a client that consumes several pages. Establish the API's contract first: a live collection and a fixed snapshot can have different valid behavior when records change during traversal.

Pagination testing vs general API testing

The API Testing Checklist covers the wider endpoint contract, including methods, validation, permissions, response data, and errors. Pagination testing follows one collection across a sequence of requests. A correct first response does not establish that later pages return the remaining records.

This guide focuses on that sequence and its boundaries. For broader endpoint scenarios, use the API Test Cases Checklist. It does not cover implementing pagination, database indexing, UI infinite scrolling, or a complete API load test.

When to use this checklist

Run focused pagination checks when:

  • a list endpoint adds pagination or changes its default or maximum page size;
  • page or offset navigation changes to cursor-based continuation;
  • filtering, ordering, visibility rules, or response metadata change;
  • a client, integration, or export starts fetching several pages;
  • an incident reports missing records, repeated records, incomplete exports, or a loop that never ends;
  • a growing collection exposes failures that small fixtures did not reveal.

For a narrow change, test the affected rule and a complete multi-page traversal. For a migration, also exercise clients that use the previous pagination contract.

Quick API pagination testing checklist

Before accepting a paginated endpoint, check that:

  • an omitted page size produces the documented default;
  • a requested size of one returns no more than one record;
  • a size above the maximum follows the documented rejection or cap policy;
  • the first page begins at the documented page number or offset;
  • the returned next link or cursor retrieves the expected continuation;
  • every expected ID appears exactly once when traversing a fixed, uniquely identified dataset;
  • records with equal sort values remain in the expected order under the agreed tie-breaking rule;
  • filters remain effective on every page;
  • a final partial page uses the documented end signal;
  • a full final page does not force the client to invent its own end signal;
  • an empty page with a valid continuation is handled according to the contract;
  • malformed or expired continuation values produce the documented response;
  • permissions are enforced again when requesting later pages;
  • a failed request can be retried without silently losing or processing records twice;
  • inserts, updates, and deletions between requests match the stated consistency policy;
  • the client completes an agreed larger fixture within its request and response-time budgets.

Full API pagination testing checklist

1. Record the pagination contract

Define what counts as a correct traversal before testing. Parameter names alone do not explain ordering, termination, or consistency.

Check that:

  • the supported method is identified: page number, offset, cursor, returned links, or a documented combination;
  • page numbering and offset semantics identify the starting position;
  • the default and maximum size, and the handling of zero or omitted size, are documented;
  • continuation and end-of-results signals have explicit meanings;
  • the default ordering and treatment of equal sort values are defined;
  • the expected behavior after changing filters, sorting, or page size during traversal is recorded;
  • the contract states whether traversal uses live data, a snapshot, or another consistency model;
  • any total count is identified as exact, estimated, or unavailable.

Use the API Documentation Checklist to review missing contract details. If a material expectation is undefined, record that gap rather than assigning an arbitrary expected status or result.

2. Prepare fixtures that expose boundary errors

Use known record IDs and an independently prepared expected order. Do not obtain the expected set by calling the same paginated endpoint being tested.

Check that:

  • fixtures include no records, one record, and several pages of records;
  • collections include one fewer than a page, exactly one page, and one more than a page;
  • another fixture fills an exact multiple of the requested page size;
  • several records share the primary sort value so tie handling is observable;
  • filtered fixtures contain both matching and excluded records across page boundaries;
  • separate identities have different visible subsets when permissions affect the endpoint;
  • the baseline fixture remains unchanged during completeness checks;
  • mutation tests can insert, update, or delete known records between selected requests.

For a size of 10, useful fixed collection counts are 0, 1, 9, 10, 11, 20, and 23. Give the records recognizable IDs so a missing boundary item is easy to identify.

3. Check the first page and page-size boundaries

Keep the same fixture and ordering while varying the requested size. Count returned records and inspect continuation metadata together.

Check that:

  • omitting the size returns the documented default and correct first records;
  • requesting a size of one returns at most one record and the required continuation;
  • requesting the supported maximum does not return more records than that maximum;
  • a value above the maximum produces the documented error or effective cap;
  • zero, negative, fractional, and nonnumeric values each follow their documented validation rule;
  • the effective size is reflected correctly wherever the API reports it;
  • changing size between requests is accepted, rejected, or restarts traversal as the contract specifies;
  • a short response does not cause the client to stop when the API still signals continuation.

Treat page size as an upper bound unless the endpoint explicitly guarantees a full page while records remain. A request for 10 and a response containing seven records require checking the continuation signal, not just the array length.

4. Verify page-number and offset navigation

For endpoints that use page or offset parameters, calculate the expected slice from a fixed ordered fixture. Test navigation directly as well as through any returned links.

Check that:

  • the first page number or starting offset returns the correct first record;
  • the next page or offset starts at the expected boundary record;
  • direct requests for a later supported position return the independently calculated slice;
  • the same valid position returns the same IDs while the fixture remains unchanged;
  • a position beyond the fixed collection follows the documented empty-result or error behavior;
  • negative, fractional, malformed, and excessive positions follow the agreed validation policy;
  • combining page size and position does not introduce an off-by-one omission or overlap.

For a zero-based offset and size of 10, offsets 0, 10, and 20 should select the first, second, and third slices of the unchanged fixture. A page-number API may use a different starting number; test its documented convention.

5. Verify cursor and returned-link continuation

A cursor is a value used to continue traversal from a previous response. Treat it as supplied continuation data rather than guessing its contents or constructing the next value.

Check that:

  • using the returned cursor or next URL advances to the expected records;
  • the client preserves the full value when passing it into the next request;
  • the continuation request retains the required filter, sort, and scope context;
  • changing a parameter associated with the cursor follows the documented continuation policy;
  • previous-page navigation works when the endpoint supports it;
  • optional first, previous, or last links are handled when absent;
  • the returned continuation can be followed without relying on the cursor's internal structure.

For example, GitHub's REST API pagination documentation describes next-page URLs in the response's Link header. The available link relations and pagination parameters can differ. Test the actual endpoint rather than requiring every response to contain first, previous, next, and last links.

6. Compare a complete traversal with the expected dataset

This is the main completeness check. Follow the documented continuation until its end signal, recording each page's IDs before combining the results.

Check that:

  • the combined IDs match the independently prepared visible dataset;
  • every expected ID appears once when the contract defines unique records and the fixture is fixed;
  • no unexpected or excluded ID appears in the combined result;
  • the concatenated sequence matches the expected order, including page boundaries;
  • the total number of returned records agrees with the fixture, independently of any reported count;
  • repeating the traversal from the beginning produces the same result for the unchanged fixture;
  • the client terminates without returning to an already visited continuation state.

Keep both the raw sequence and the set of unique IDs. A client that removes duplicates may show the right unique count while hiding overlapping pages or skipped records elsewhere.

7. Check ordering and equal sort values

Small datasets with distinct timestamps can conceal unstable boundaries. Use records that share the primary sort value and span more than one page.

Check that:

  • the default order matches the documented sort rule;
  • an explicit supported ascending or descending order applies across the whole traversal;
  • records with equal primary values follow the agreed secondary or unique tie-breaking rule;
  • tied records split across pages are neither omitted nor repeated in the fixed fixture;
  • null or missing sort values occupy the documented position when supported;
  • changing the requested sort direction starts or continues traversal only as the contract permits.

If equal values have no defined order, record the limitation and agree how completeness will be established. Do not assume that a timestamp alone identifies a unique page boundary.

8. Check filters and query context on every page

Compare the full filtered result with a known subset. A correct first page can conceal a continuation request that drops the original filter.

Check that:

  • every page contains only records matching the active filter;
  • the combined result contains every matching visible record in the fixed fixture;
  • supported combinations of filters and sorting remain effective after continuation;
  • a filter with no matches returns the documented empty result and end signal;
  • changing a filter mid-traversal produces the documented rejection, restart, or new result context;
  • returned links preserve required query values without dropping or duplicating them;
  • search text or date-range boundaries remain consistent across pages when supported.

Keep the expected filtered set separate from the endpoint's reported count. The count and returned pages can share the same defect.

9. Test empty pages and end-of-results detection

Test the termination rule directly. Depending on the contract, a short or empty page may still provide a continuation value.

Check that:

  • an empty collection returns the documented response shape and end signal;
  • a final partial page does not advertise another page when the contract says the collection is complete;
  • an exact full-page ending is handled without assuming that another full page must exist;
  • an empty intermediate page is followed when the response still provides a valid continuation;
  • a missing, empty, or null continuation is interpreted according to the endpoint's defined representation;
  • a repeated continuation that makes no progress is detected rather than retried indefinitely;
  • a client request or time budget produces an explicit incomplete outcome instead of claiming a complete result.

Google's AIP-158 pagination guidance allows a response to contain fewer requested results, including zero, before the collection ends; in that model, the next-page token determines whether to continue. It also states that page tokens do not provide authorization. These are rules of that API design model. Identify your endpoint's end signal and verify permissions independently of continuation data.

10. Check inserts, updates, and deletions between pages

Use a separate mutation fixture so the stable baseline remains reproducible. Record the collection before and after each change, and evaluate the result against the stated consistency model.

Check that:

  • an inserted record before the current position has the documented effect on later pages;
  • an inserted record after the current position is included or excluded according to the live or snapshot policy;
  • deleting a previously returned record does not cause an undocumented shift in remaining results;
  • deleting the record associated with a cursor follows the defined continuation behavior;
  • updating a sort value handles the record's movement according to the consistency policy;
  • changing a filter-relevant field has the defined effect on membership during traversal;
  • any snapshot expiry or consistency limitation is visible to the client rather than silently presented as a complete snapshot.

A live offset traversal can shift when records are inserted or removed before an offset. Cursor-based continuation also needs a defined mutation policy. Neither the word "cursor" nor a successful response establishes snapshot consistency.

11. Check malformed, expired, and incompatible continuation values

Use known invalid inputs and controlled token expiry when the system supports it. Inspect both the response and the client's next action.

Check that:

  • a malformed cursor returns the documented validation response;
  • an unknown or altered cursor does not silently select an unrelated position;
  • an expired cursor follows the defined error or restart policy;
  • a cursor from another endpoint or collection is handled according to the contract;
  • an incompatible filter or sort context produces the documented response;
  • restarting after a rejected cursor is explicit and does not silently append first-page records to an existing result;
  • the error includes enough contract-supported information for the client to recover without exposing protected data.

Use the API Error Handling Testing Checklist for the wider error response contract. Do not require a particular status code or expiry period merely because another API uses it.

12. Verify visibility on later requests

Pagination must not turn a permitted first request into unrestricted access to later records. Use approved test accounts and known visible subsets.

Check that:

  • later requests return only records the requesting identity is permitted to see;
  • using a continuation without required authentication follows the protected endpoint's access rules;
  • another identity cannot use a cursor to gain access to the original identity's protected records;
  • an identity or permission change during traversal is handled according to the agreed visibility and consistency policy;
  • counts and continuation metadata do not expose collection information that the identity is not allowed to receive;
  • scoped collection or tenant parameters remain effective on every page.

Verify access against the requesting identity, not against possession of a valid cursor. Keep this check focused on pagination; it does not replace a full API authorization review.

13. Test request failures, retries, and resumption

Interrupt a request after at least one successful page. Confirm what the client retains and which continuation it uses when recovering.

Check that:

  • a failure on a later page is reported as an incomplete traversal;
  • retrying an unchanged page request follows the endpoint's consistency policy and does not skip the failed page;
  • retrying or replaying a successful response does not process its records twice in a client that promises single processing;
  • a resume checkpoint advances only at the stage defined by the client's processing policy;
  • resuming with an invalid checkpoint follows an explicit recovery or restart path;
  • a cancelled traversal retains or discards partial results as the client contract specifies;
  • the final success state is reached only after the documented end signal and required record processing.

Distinguish receiving a page from processing its records. A client that stores its next cursor before processing can resume beyond records it never handled.

14. Check counts, response shape, and navigation metadata

Use metadata as supporting evidence rather than the only proof of completeness. Compare it with the fixed fixture and the returned records.

Check that:

  • an exact total matches the expected visible, filtered fixture;
  • an estimated total is identified and is not treated by the client as an exact stopping rule;
  • a missing optional total does not prevent valid continuation;
  • counts represent records rather than pages unless another meaning is explicitly defined;
  • the item and pagination fields retain the agreed types across first, intermediate, last, and empty responses;
  • reported page positions, sizes, and navigation links agree with the request and effective result;
  • an optional last-page link is not required when the endpoint cannot provide it.

An exact count from a frozen fixture is useful evidence. A count from a changing collection may describe a different moment than a later page, so apply the documented count semantics.

15. Check larger collections and client compatibility

Use an agreed larger test collection to expose long traversals and later-page failures. This is a focused correctness and budget check, not a complete performance benchmark.

Check that:

  • a full traversal of the agreed larger fixture reaches the end with the expected IDs;
  • later pages and high supported positions meet the agreed response-time target;
  • default and maximum sizes keep response sizes within the client's agreed limits;
  • the client does not exceed its defined request, time, or memory budget without reporting incomplete results;
  • supported existing clients still interpret continuation and termination after an API change;
  • a client that previously expected all records in one response is tested explicitly when pagination is introduced;
  • failure evidence records request parameters, page position or continuation reference, returned IDs, and the observed end state.

Record the fixture size, client version, and completion result alongside timing. Fast first-page responses do not establish that a long traversal completes correctly.

Worked pagination testing examples

These examples use invented endpoints and fixed rules. IDs, ordering, and continuation behavior are stated so the expected results can be calculated without trusting the endpoint under test.

Example 1: Traverse 23 records in pages of 10

  • Contract: Page numbers start at one, results sort by ID ascending, and the final nonempty page has no next-page link.
  • Fixture: Exactly 23 visible records, R01 through R23, with no changes during traversal.
  • Action: Request the first page with size 10 and follow each returned next-page link.
  • Expected pages: Page one contains R01 through R10; page two contains R11 through R20; page three contains R21, R22, and R23.
  • Expected completion: The raw combined sequence has 23 records and 23 unique IDs, and the third response has no next-page link.
  • Failure this catches: Returning R10 again at the start of page two or omitting R11 at the boundary.

Example 2: Keep tied sort values stable across pages

  • Contract: Sort by creation time ascending, then ID ascending. The secondary ID order is part of the contract.
  • Fixture: Five records, A1 through A5, all with the same creation time.
  • Action: Traverse with page size two while leaving the fixture unchanged.
  • Expected pages: A1, A2; then A3, A4; then A5.
  • Expected completion: Each of the five IDs appears once, in the stated order.
  • Failure this catches: A page boundary based only on creation time that skips the remaining tied records, or an unspecified ordering that overlaps pages.

Example 3: Continue after an empty intermediate page

  • Contract: A nonempty next token means continue, even when the item array is empty. An absent next token means the collection is complete.
  • Fixture responses: The first response contains R01 and R02 with token next-A; the second is empty with token next-B; the third contains R03 with no next token.
  • Action: Follow the returned tokens without deriving them from the item count.
  • Expected completion: Three requests return the combined IDs R01, R02, and R03, and traversal stops after the third response.
  • Failure this catches: A client that stops after the empty second response and reports a complete two-record result.

Example 4: Observe an insertion during live offset traversal

  • Contract: The endpoint uses live data, zero-based offsets, ascending ID order, and size three. It does not promise a snapshot.
  • Starting fixture: O1 through O6. The first request at offset zero returns O1, O2, and O3.
  • Change: Insert O0 before requesting offset three. The current ordered collection becomes O0 through O6.
  • Expected next page under this rule: Offset three now returns O3, O4, and O5. The raw traversal repeats O3 because the positions shifted.
  • Assessment: Record this live-data limitation rather than claiming a snapshot defect. If the endpoint instead promises a stable snapshot, that repeated boundary record would violate the stated expectation.
  • Client decision: Verify that the consuming workflow handles the documented limitation or requires a stronger consistency contract. Deduplicating O3 alone does not establish complete coverage of changing data.

Common mistakes

1. Checking only the first response

The first page can have the right schema and records while every continuation returns the same page. Verify a complete sequence and its final state, not just one successful request.

2. Comparing only a total count

A traversal can return 23 entries containing one duplicate and one omission. Compare the raw IDs, their unique set, and their order against the known fixture.

3. Ending on any short or empty page

Item count and end-of-results metadata are different signals. Use the contract's termination rule, including empty intermediate responses when supported.

4. Testing only unique sort values

Distinct timestamps hide tie-boundary defects. Place several records with the same primary value on both sides of a page boundary and apply the agreed tie rule.

5. Assuming cursors guarantee a snapshot

A continuation value can identify a position without freezing the collection. Define mutation expectations before treating a changing traversal as a missing-record defect.

6. Letting deduplication hide endpoint defects

Removing repeated IDs may conceal overlapping pages and does not recover an omitted record. Preserve the raw page evidence before any client transformation.

7. Calling a partial traversal successful

A request limit, timeout, failed page, or rejected cursor can leave a usable partial result. The client should label it according to its contract and avoid presenting it as a complete collection.

FAQ

Prepare an independent list of visible IDs and their expected order, freeze the fixture, and follow the endpoint's documented continuation. Compare the raw combined sequence, unique ID set, and completion signal with those expectations. Repeat with boundary collection sizes and filters.

Page and offset tests calculate expected slices from numeric positions. Cursor tests follow continuation values supplied by previous responses and check their associated query context. All methods still need completeness, ordering, boundary, and termination checks against the endpoint's own contract.

Only when the contract defines it that way. Some APIs can return an empty page with a valid next token. Check the defined next link, token, or other end signal instead of assuming that array length determines completion.

Keep the IDs from each page before deduplication. Compare the combined result with an independently prepared expected set and count each ID's occurrences. For a fixed unique-record fixture, an absent expected ID is an omission and a repeated ID is an overlap unless the contract explicitly defines another result model.

That depends on the consistency contract. A fixed snapshot and a live query can produce different valid results. Test inserts, deletions, and sort or filter updates separately, record when each change occurs, and evaluate the sequence against the promised model.

A continuation cursor and an authentication credential serve different purposes. Verify that each request enforces the endpoint's access rules, and that possessing a cursor cannot expand the requesting identity's permitted data. Test this with approved accounts and fixtures.

Use counts around the requested page size, an exact multiple, a partial final page, and several full pages. A size of 10 can be checked with 0, 1, 9, 10, 11, 20, and 23 records. Add a separate larger fixture for agreed performance and traversal budgets; there is no universal dataset size for every endpoint.

Ready to turn this guide into a working QA project with statuses, comments, and CSV export?