REST API Design Cheatsheet: Pagination and Performance
When a REST API returns a set of records, pagination splits the records across multiple responses. Without pagination, a request for many…
When an AI agent reads records from an API, the API tells the client how to request the next page. One API might return a page number, another an opaque cursor (a token the client sends back without interpreting), and a third a backend key. If an integration treats those signals as interchangeable, it can stop early, repeat records, or make unnecessary requests.
Have each connector or workflow present pages consistently while following the API’s rules. The API defines how to request the next page. The connector translates those rules, and a workflow that follows fixed steps makes repeated requests when complete results matter. Give the agent only the results its task needs, up to a set limit, instead of expecting it to fetch every page.
Pagination lets a client retrieve a large result set across several smaller responses. APIs use different rules for requesting the next page. Offset or page-number pagination asks for a position such as page or offset. Cursor pagination returns a token that the client sends back to request the next page. Other APIs return a boundary key or timestamp. GraphQL connections commonly pair edge cursors with pageInfo, which reports whether another page exists.
These mechanisms share a purpose, but their tokens and stop signals do not mean the same thing. Google’s AIP-158 recommends opaque page tokens and describes an empty next_page_token as the end signal for APIs following that guidance. The GraphQL Cursor Connections specification defines a connection structure with edge cursors and page information. DynamoDB uses LastEvaluatedKey from one response as ExclusiveStartKey in the next request.
A connector should translate field names and response structures without changing these rules. It should pass an opaque token back unchanged, preserve filters and sorting when the API binds the token to those parameters, and use the endpoint’s documented end-of-results signal.
Page length alone does not reliably indicate completion. AIP-158 allows an API to return fewer results than requested, including no results, while more pages remain. DynamoDB also documents cases where a filtered query returns no matching items but still includes a continuation key. The connector should therefore stop only when the API’s documented signal says to stop.
An internal page structure lets different connectors present results consistently to a workflow or agent. For example, a connector could translate provider-specific responses into this proposed shape:
{
"items": [],
"has_more": true,
"continuation": "opaque-provider-token",
"page_number": 1,
"limit": 50
}
This shape is an implementation choice, not a cross-provider standard. The connector should populate has_more from the endpoint’s actual stop rule and preserve the provider’s continuation value. For endpoints without page numbers, the connector should omit page_number or define its meaning clearly so readers do not assume every API supports numbered pages.
A continuation token also does not guarantee that the collection stays unchanged during a multi-page read. The API may return pages while records are added, removed, or reordered. Before using pagination for a sync or export, check the provider’s ordering and consistency guarantees. Keep filters and sort parameters fixed when the provider requires them, and use a stable sort with a tie-breaker, a field that orders records whose sort values match, when the endpoint documents one.
Who retrieves the pages depends on what the agent needs. A direct tool call works well for a bounded lookup, such as finding a few matching records. A workflow or backend job fits repeatable retrieval, exports, and syncs because it can follow every page, enforce limits, and save progress. An integration platform can host those steps and expose a smaller result to the agent.
| Agent task | Pagination owner | What the agent receives |
|---|---|---|
| Interactive lookup | Connector or narrow API wrapper | A filtered, bounded set of records |
| Repeatable business task | Workflow or integration platform | Selected records, a summary, or a status |
| Bulk export or sync | Backend job or asynchronous workflow | A job status, saved output, or artifact reference |
| Access across many systems | Tool gateway backed by connectors | Task-specific results from tools with explicit pagination behavior |
An agent-accessible tool does not automatically make the agent responsible for retrieving every page. MCP, the Model Context Protocol, can paginate lists used to discover server capabilities and resources. That mechanism does not define how an API-backed tool retrieves its own business records; the tool implementation still follows the backend API’s contract. The MCP Python SDK pagination guide describes pagination for MCP list handlers.
Product documentation illustrates how integration platforms can divide this work. Workato describes recipes that assign tasks to agents and resume after the agent returns data; its documentation also recommends returning only necessary fields and preprocessing large datasets. MuleSoft’s Connector Builder supports configuring connector pagination and can suggest a strategy from API documentation, but its guidance calls for reviewing the suggestion and regenerating the connector to apply the behavior. Those are product-specific capabilities, not evidence that a platform-generated configuration is correct for every endpoint. See Workato’s orchestration documentation and MuleSoft’s pagination documentation.
A deterministic page loop should have limits separate from the provider’s per-page limit. Set a maximum number of pages, records, response bytes, or runtime for each agent task. Respect the provider’s accepted page size: some APIs reduce an excessive request, while others reject it. The OnSched pagination documentation, for example, distinguishes page-based navigation for an appointments endpoint from cursor pagination recommended for exports and backend ingestion.
When a temporary error interrupts a page request, retry that same continuation request rather than advancing to a new token or reconstructing the cursor. Before relying on this behavior, verify that the API supports retrying a request with the same continuation state. Keep the original filters and sort settings when the provider ties its cursor to them.
Agent behavior adds another reason to control the loop outside the model. A 2026 study, “Agents Don’t Paginate”, found no agent-initiated second-chunk requests in one public MCP-middleware log corpus, though the authors did not find the same pattern in independent production datasets. Its accuracy test covered only locating files, so the findings cannot establish that agents never paginate. Complete exports should therefore run independently of an agent’s decision to request every next page.
For a question-answering task, expose search, filtering, aggregation, or another operation that returns relevant records within a known bound. For complete retrieval, have a workflow or backend job walk the pages and pass the agent a summary or reference to the stored output. Automatic pagination can simplify client code, but collecting every page in an agent-facing call can return more data than the task needs.
Give Vroni a GitHub issue, bug report, spec, or rough idea. It reads the repo, plans the change, writes code, runs checks, and works toward a review-ready pull request.
Take a look at vroni.com