API documentation · Research synthesis
Does fetching every API page give you a complete export?
What API pagination guarantees, where records can be missed, and how to document continuation, snapshots, retries and export completeness.
Reaching the end of a paginated response does not, by itself, prove that an export contains every record you intended to collect. The endpoint also needs a defined population, ordering and consistency policy. We connect official API documentation to a practical pagination contract, with worked examples and proposed tests for documentation teams.
Key findings
A short or empty page is not a universal stopping condition. Follow the endpoint’s documented continuation signal. Slack DynamoDB Query
A cursor and a consistent snapshot solve different problems. Elasticsearch documents a point-in-time mechanism; DynamoDB explicitly distinguishes item-level consistency from scan snapshot isolation. Elasticsearch DynamoDB Scan
Continuation is part of the request contract. Microsoft Graph tells clients to use the full next-page URL, and Google’s design guidance requires authorization independently of page tokens. Microsoft Graph Google AIP-158
Our proposed acceptance record separates reaching the end, saving the returned items and establishing completeness. These are distinct checks, not a measured vendor score.
How we researched this
Research synthesis of eight official documentation pages from seven organizations, including Google API design guidance, independently opened on November 14, 2026. Sources were selected to examine different continuation signals and both point-in-time behavior and explicit consistency limitations. We checked the named sections against the claims recorded below. These are documentation observations, not live API measurements or a representative survey. Examples and acceptance scenarios are our analysis; they were not executed against providers. Access dates identify when we read each page, not when its behavior was introduced.
Start by defining what a complete export means
Imagine a customer exporting every active account before moving to a new system. The script follows each next-page link, receives successful responses and finishes without an exception. That sounds complete. But complete relative to which accounts: those active at the start, those active when each page was read, or those still active when the job ended?
Those are different requirements. An export guide should choose one before showing the loop. Otherwise, two developers can implement the same endpoint correctly and still disagree about whether the resulting file is usable.
We propose separating three questions:
- Traversal: Did the client follow the documented continuation sequence until its terminal signal?
- Capture: Did the client save the intended items from every successful response, without silently discarding or replaying work?
- Completeness: Does that saved set match the population and time boundary promised to the reader?
The third claim is stronger than the first two. A traversal log cannot supply a snapshot guarantee that the API contract never made. Conversely, an API with an explicit consistent view deserves credit for that stronger behavior. The task is to identify the guarantee, not assume that all pagination is unreliable.
| Reader’s goal | Definition to settle first | Evidence to request |
|---|---|---|
| Browse a changing activity feed | A useful next page of current results | Documented ordering and navigation behavior |
| Export a fixed reporting period | Which records and revisions belong to the period | Supported time filters and a consistency policy |
| Recreate a dataset at one moment | The exact population at a defined boundary | An explicit snapshot or equivalent export contract |
| Keep a local copy updated | How creates, updates and removals are represented | A documented synchronization protocol and recovery path |
This is our decision table, not a claim that any particular list endpoint supports every goal. A browse endpoint can be excellent for browsing while unsuitable for a financial reconciliation or a one-time migration.
Why a short page is not the end
For its cursor-paginated methods, Slack explicitly warns that a response can contain fewer items than the requested limit while more results remain. Its cursor-paginated methods use the next cursor to decide whether to continue. Cursor absence, null or emptiness signals the end. Slack pagination
DynamoDB Query has an additional wrinkle: filtering happens after the page’s read limit. A response can therefore contain no matching items and still provide a LastEvaluatedKey. That key means another request is required to establish completion, not that another matching item is guaranteed. DynamoDB Query pagination
These details belong beside the example loop. Placing them only in a generic API reference leaves the person copying an export example to invent the most important branch.
| Documented interface | Continuation information | Detail a guide should preserve |
|---|---|---|
| Slack cursor methods | response_metadata.next_cursor | Result count alone does not establish completion. Source |
| GitHub REST pagination | Link header with rel="next" | Follow supplied links; pagination parameters vary by endpoint. Source |
| Microsoft Graph paging | @odata.nextLink | Use the complete URL until the property is no longer returned. Source |
| Stripe v1 list endpoints | has_more and object-ID cursors | The documented v1 list interface differs from the v2 interface. Source |
| DynamoDB Query | LastEvaluatedKey | Continue with ExclusiveStartKey until the key is empty or absent. Source |
Do not turn this table into a universal client algorithm. Each row has its own response shape, failure handling and endpoint exceptions. A guide should identify the actual operation and API version, then show that operation’s terminal condition.
Our proposed review question is simple: if the first response contains zero matching items and a valid continuation, does the example continue, report an error, or announce an empty export? The answer should follow the documented contract rather than the author’s intuition about what a page looks like.
A six-record example shows what page counts cannot prove
Consider a hypothetical offset-based list ordered alphabetically. This is a reasoning example, not a measured result from any named API.
At the start, the records are A, B, C, D, E and F. The client requests three records and receives A, B and C. Before the next request, another process deletes A. The current list is now B, C, D, E and F. If the next request skips the first three current records, it receives E and F. D was never returned, even though the client advanced by the number of records it had already received.
Now reverse the change. Start again with A through F, read A through C, then insert a new record before A. Skipping the first three current records can return C again. Removing duplicate IDs from the export can address that repeated row, but it cannot reconstruct a row that was never observed.
The assumptions matter: ordering is evaluated on each request, the offset is applied to the current list and there is no snapshot. This example does not establish how GitHub, Stripe or any other provider implements a specific endpoint. It shows why the documentation needs to state more than a page number.
A second, separate issue concerns the way completeness is checked. Suppose an expected test dataset contains A, B and C, while the export contains A, B and B. The count is three in both cases. Equal counts do not establish equal membership. Even matching unique IDs would not establish that every field came from the same moment.
For a controlled fixture, compare the expected IDs and relevant values. For a changing production dataset, first establish what expected means. If no authoritative comparison set exists, say that traversal completed and describe the consistency limitation. Avoid upgrading a counter into proof.
A cursor is not automatically a snapshot
Elasticsearch documents the distinction directly. With search_after, a refresh between requests can change ordering and produce inconsistent pages. Its point-in-time option preserves the index view for the search sequence, subject to its lifetime and request requirements. The guide also explains the importance of a unique tie-breaker: without one, paged results can miss or duplicate hits. Elasticsearch pagination
DynamoDB Scan consistency has a different boundary. DynamoDB Scan can perform strongly consistent item reads, but the documentation explicitly says that this does not provide snapshot isolation for the scan. Item-level consistency should not be described as a guarantee that the entire traversal represents one moment. DynamoDB Scan
That is meaningful contrary evidence to a simplistic rule such as “switch to cursors and exports are fixed.” Continuation position, ordering and the view of the dataset are separate concerns. A stronger API may address all three, but its guide must identify the mechanism and conditions.
For documentation authors, ask the service owner to approve one precise statement about concurrent changes. Examples of the questions to resolve include:
- Can a new record appear after traversal starts?
- Can a record move across the continuation boundary when its sort field changes?
- What happens if a record disappears before the client reads it?
- Does the operation preserve a view of record values as well as membership?
- What happens when the preserved view expires or becomes unavailable?
Do not infer the answers from a cursor’s appearance. An opaque string may identify a position, stored server state or something else. Its spelling is not evidence of a consistency guarantee.
If the product has no supported way to make a point-in-time export, write that limitation plainly. Offer only alternatives the product actually supports, such as a dedicated export operation. A warning plus a correct workflow is more useful than a promise the endpoint cannot meet.
Preserve the request and explain recovery
Microsoft Graph instructs clients to use the entire nextLink URL rather than extract its skip token into a different request. For directory-resource requests that depend on custom headers such as ConsistencyLevel, those headers need to be set explicitly on subsequent requests because they are not automatically carried forward. A URL and the complete request context are not always the same thing. Microsoft Graph paging
Google AIP-158 is design guidance, not proof of every Google endpoint’s implementation. It permits short or zero-item pages, allows changing page size while other arguments stay fixed, and requires authorization independently of the page token. It also permits token expiry. Google AIP-158
Slack supplies a practical recovery constraint: its cursors expire and should not be stored for hours or days. That is a reason to distinguish an immediate continuation from a durable restart checkpoint. Slack pagination
Our recommendation is to document recovery at two levels. First, explain the provider’s rules for retrying a failed request, including any token-specific exceptions. Second, explain what the example does with records it already saved. These are different responsibilities.
Consider a hypothetical exporter that writes a page to a destination and crashes before recording progress. A restart may write that page again. If it records progress first and crashes before writing, it may skip the page’s records. The guide should identify its intended recovery behavior and destination assumptions. A stable record ID can help design replay-safe writes, but it does not by itself decide which revision should win.
An expired token must not become an empty-success result. Recommend a visible incomplete status and the supported restart path. Restarting from the beginning can change the population unless the original view is still available. Explain whether the new run replaces, merges with or remains separate from the previous attempt.
Our recommendation is to advance a durable checkpoint only in accordance with the destination’s commit and recovery model. Without atomic coordination, document the replay or reconciliation strategy rather than promise exactly-once output. This is client-side durability design, not a provider pagination guarantee.
The implementation may need transactions or other coordination; a documentation example should not imply that two unrelated writes become atomic just because they appear beside each other in a code block.
The pagination contract to put beside an export example
A parameter table is necessary, but it is rarely the whole explanation a reader needs. We propose the following contract for an export guide. Fill it using the endpoint’s implementation and approved product behavior. An unknown should become a documented limitation or an engineering question, not an invented default.
| Contract field | Question the guide must answer | Review evidence |
|---|---|---|
| Population | Which tenant, filters, permissions and resource types are included? | A concrete example request and its intended scope |
| Ordering | Which fields determine order, including ties? | Approved behavior for equal sort values |
| Continuation | What exact field or link advances the operation? | A response example with a nonterminal page |
| Completion | Which signal ends traversal? | A terminal response and a short-page counterexample where applicable |
| Consistency | What happens while records change? | An explicit guarantee or limitation from the service owner |
| Recovery | What survives a timeout, crash or expired token? | A restart example with an incomplete result handled visibly |
| Verification | How can the reader check the exported result? | A known fixture and clearly scoped checks |
The most useful placement is close to the task. A reader should not have to combine five distant reference pages to discover that the example cannot resume tomorrow.
For an API without snapshot semantics, a proposed disclosure might say: “This guide follows the list endpoint to its final page. It does not promise that all returned records reflect one moment. Review the endpoint’s concurrent-change behavior before using this result as a point-in-time export.” This is suggested wording, not a description of a particular provider.
For a snapshot-backed operation, identify when its view is established, how long it remains usable and what failure looks like. Keep that explanation separate from destination durability. The remote service preserving a view does not establish that a client saved every response.
This adds a narrow operational layer to reference documentation. Our OpenAPI workflow coverage report examines the broader distinction between describing an interface and explaining how to complete a task.
Test the guide against failures that a small demo hides
The following is a proposed acceptance exercise for a team’s own test environment. We did not run it against the cited providers. Choose cases supported by the endpoint and record the exact API and client versions. A case that is not applicable should have a reason rather than a silent pass.
| Scenario | What to inspect | A misleading result to reject |
|---|---|---|
| Short page with valid continuation | The next request and final saved set | Declaring completion because the page is under the limit |
| Empty filtered page with continuation | Whether traversal advances correctly | Announcing that the entire dataset is empty |
| Equal sort values across a boundary | IDs around the boundary under the promised ordering | Assuming timestamps are unique without a contract |
| Insert, update or delete during traversal | Behavior relative to the documented consistency policy | Calling a changing view a snapshot |
| Interrupted destination write | What is saved, replayed and checkpointed | A finished status after missing or duplicated output |
| Expired continuation | Explicit failure and the supported restart procedure | Converting token rejection into end-of-list |
| Changed filter or authorization context | The documented rejection or changed scope | Silently labeling two different populations one export |
| Retry at a page boundary | Provider-specific continuation and local replay behavior | Advancing despite an uncommitted or failed page |
Use a fixed dataset first so that expected membership and values are known. Then add controlled changes at specific boundaries. Record the change timing, request sequence, observed IDs and final status. Timing-dependent observations should not be generalized beyond the conditions tested.
For the interruption case, identify which operation actually failed. A network timeout before the response, a destination write failure and a crash after saving have different recovery implications. A test that only throws an exception at the top of the loop does not exercise all three.
The acceptance criterion is agreement between the documented promise and the observed behavior. It is not that every API must provide snapshots, accept permanent tokens or support the same retry algorithm. When the service intentionally offers weaker guarantees, the guide should help readers choose a suitable task and recognize its limits.
Keep completeness claims narrower than the evidence
A useful review can be performed in three passes. Have an API owner verify the contract, a developer follow the example and a documentation reviewer check the language around success. Each pass should produce evidence about its own question rather than one broad “works” checkbox.
Ask the developer to report more than the number of pages requested. For a controlled test, useful observations include the expected IDs, observed unique IDs, repeated IDs, missing IDs and relevant value differences. Keep counts tied to that fixture. Do not publish them as a provider’s general error rate.
For a real export, a completion record could identify the operation, API version, request scope, start and finish times, continuation termination and output destination. Include a snapshot identifier only if the API supplies a meaningful one and its storage is appropriate. As an operational precaution, keep usable continuation tokens and URLs out of public examples, analytics and ordinary logs unless their disclosure has been reviewed. Use synthetic placeholders in documentation. A token not granting authorization does not establish that its contents are appropriate to publish.
The reader-facing status should follow the evidence. “Reached the final page” describes traversal. “Saved all responses from this run” describes capture. “Recreated the dataset at the stated time” requires the stronger completeness contract and verification. If the last claim cannot be established, the first two can still be useful.
Review pagination guidance when the endpoint’s ordering, default limits, filters, permissions, continuation mechanism or client helpers change. An apparently minor example edit can alter where a loop stops or what it preserves for recovery.
This report intentionally does not rank APIs by speed or reliability. The cited documents expose different boundaries, and the worked examples explain why those boundaries matter. For broader maintenance practices, see our API documentation testing report. The immediate improvement is smaller: make every export guide say what complete means, show how the client reaches that state, and state what the result does not prove.
Limitations
This is a purposive desk synthesis of eight public source pages, not a survey, live integration test or vendor benchmark. Endpoint-specific documentation takes precedence over a platform overview. We did not measure missing-record rates, throughput, reliability or business impact. The worked sequences are hypothetical and depend on stated assumptions. Proposed acceptance cases require validation against the team’s actual implementation. Current documentation can change; access dates are not release dates. Nothing here asserts that Docsio runs customer exports or provides snapshot semantics.
Sources
- AIP-158: PaginationGoogle · Accessed 2026-11-14
- PaginationSlack · Accessed 2026-11-14
- Paging Microsoft Graph data in your appMicrosoft · Accessed 2026-11-14
- Using pagination in the REST APIGitHub · Accessed 2026-11-14
- PaginationStripe · Accessed 2026-11-14
- Paginate search resultsElastic · Accessed 2026-11-14
- Paginating table query results in DynamoDBAmazon Web Services · Accessed 2026-11-14
- ScanAmazon Web Services · Accessed 2026-11-14