Pagination
Configure pagination helpers and auto-iterators for your SDK. Support cursor, offset, and page number pagination schemes with automatic next-page fetching.
Configuring pagination with Stainless SDKs generates a helper to fetch the next page and an auto-iterator to easily loop through items in your API. The helper makes it easy to manually paginate when needed and the auto-iterator makes consuming a list as natural as a for loop, with the iterator automatically fetching the next page when needed:
const iter: OffsetPage<Account> = await client.accounts.list()
for await (const account in iter) { if (account.name === 'Michael') { console.log(account.id) }}Pagination Scheme
Section titled “Pagination Scheme”Stainless will only use recognized pagination schemes when generating SDKs. If a method isn’t being paginated,
make sure that it has the required schema for the request and response, and that it matches the schema
in the OpenAPI spec. If a method is improperly paginated, make sure that the
x-stainless-pagination-property is set correctly.
The request and response must include all parameters and fields needed for pagination. The request
might have a limit, offset, page number, page size, or start ID; the response might have the data, a link
to the next page, or the next start ID.
You can also include parameters that aren’t strictly necessary for pagination to work. For example, it might
be appropriate to add a request parameter like sort_by, which might be an enum of the ways you can sort
across your API.
Here’s an example of a pagination scheme Stainless recognizes:
pagination: - # Name for the pagination scheme. # Stainless will use this name when generating code for pagination helpers. name: cursor_page # Type of pagination your API uses, used to set logic for fetching each page. # For the list of allowed types, see the "Pagination Type" section below. type: cursor_id request: # Specifies that paginated endpoints take a `starting_after` query param, # which pagination helpers pass cursor IDs to. starting_after: # This param name is the one your API uses. type: string x-stainless-pagination-property: # Defines the purpose of the param. purpose: next_cursor_id_param response: # Specifies that paginated responses have a `data` field # containing the contents of the requested page. data: type: array items: type: unknown x-stainless-pagination-property: purpose: items # Specifies that responses have a `next_cursor` field, # which pagination helpers will take the next cursor ID from. next_cursor: type: string x-stainless-pagination-property: purpose: next_cursor_field # Optional. Specifies where pagination parameters are located. # Can be `query` (default) or `body`. param_location: queryPagination Type
Section titled “Pagination Type”The first step in configuring pagination is to define the type of pagination your API is using. The types of pagination Stainless supports are:
cursor: A pagination scheme that uses a cursor (a string or a number to indicate the element to start from) to paginate through a list of items.cursor_id: Similar to cursor pagination, but the cursor comes from an id property of the response items.cursor_url: A pagination scheme that simply returns a URL to fetch from to retrieve the next page of results.offset: A simple pagination scheme that uses an offset (the number of entries to skip) and limit (number of elements to fetch) to paginate through a list of items.page_number: Similar to offset pagination, but instead of an offset, which indexes on the items,page_numberindexes on chunks of elements to skip.
Cursor Pagination
pagination: - name: my_cursor_page type: cursor request: next: type: string x-stainless-pagination-property: purpose: next_cursor_param limit: type: integer response: my_data: type: array items: type: object next: type: string x-stainless-pagination-property: purpose: next_cursor_fieldExample OpenAPI Specification
openapi: 3.1.0paths: /accounts: get: parameters: - name: next in: query schema: type: string - name: limit in: query schema: type: integer responses: '200': description: 'success!' content: application/json: schema: type: object properties: my_data: type: array items: type: object next: type: stringCursor ID Pagination
pagination: - name: my_cursor_id_page type: cursor_id request: starting_after: type: string x-stainless-pagination-property: purpose: next_cursor_id_param ending_before: type: string x-stainless-pagination-property: purpose: previous_cursor_id_param limit: type: integer response: my_data: type: array items: type: object properties: id: type: string x-stainless-pagination-property: purpose: cursor_item_id required: - idExample OpenAPI Specification
openapi: 3.1.0paths: /accounts: get: parameters: - name: starting_after in: query schema: type: string - name: ending_before in: query schema: type: string - name: limit in: query schema: type: integer responses: '200': description: 'success!' content: application/json: schema: type: object properties: my_data: type: array items: type: object properties: id: type: stringCursor URL Pagination
pagination: - name: cursor_url_page type: cursor_url request: page_size: type: integer response: data: type: array x-stainless-pagination-property: purpose: items next: type: string x-stainless-pagination-property: purpose: cursor_url_field from_header: LinkExample OpenAPI Specification
openapi: 3.1.0paths: /paginated/cursor_url: get: description: Test case for cursor_url pagination parameters: - name: page_size in: query schema: type: integer responses: '200': description: OK content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/MyModel' next: type: string format: uri description: The URL for the next page required: - data - next_pageOffset Pagination
pagination: - name: my_offset_page type: offset request: my_offset: type: integer description: The number of elements to skip. # this tells us to modify this param when getting the next page x-stainless-pagination-property: purpose: offset_count_param my_limit: type: integer description: The maximum number of elements to fetch. response: my_data: type: array items: type: object my_total: type: integer x-stainless-pagination-property: # total number of elements in the list purpose: offset_total_count_field my_count: type: integer x-stainless-pagination-property: # where to start the next page purpose: offset_count_start_fieldExample OpenAPI Specification
openapi: 3.1.0paths: /accounts: get: parameters: - name: my_offset in: query schema: type: integer - name: my_limit in: query schema: type: integer responses: '200': content: application/json: schema: type: object properties: my_data: type: array items: type: object my_total: type: integer my_count: type: integerPage Number Pagination
pagination: - name: my_page_number_page type: page_number request: page: type: integer x-stainless-pagination-property: purpose: page_number_param page_size: type: integer response: data: type: array items: type: object page: type: integer x-stainless-pagination-property: purpose: current_page_number_field last_page: type: integer x-stainless-pagination-property: purpose: total_page_count_fieldExample OpenAPI Specification
openapi: 3.1.0paths: /accounts: get: description: Example case for page_number pagination parameters: - name: page in: query schema: type: integer - name: page_size in: query schema: type: integer responses: '200': description: OK content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/MyModel' last_page: type: integer description: The last page number page: type: integer description: The page numberMethod level pagination
Section titled “Method level pagination”By default, Stainless automatically enables pagination for methods whose names start with list_. For example, a method named list_accounts will automatically be paginated if it matches one of your configured pagination schemes.
resources: accounts: methods: list_accounts: get /accounts # Automatically paginated due to list_ prefix list_transactions: get /transactions # Also automatically paginatedIf you have a paginated method that doesn’t follow the list_ naming convention, you can explicitly enable pagination by setting paginated: true in the method configuration:
resources: accounts: methods: search: # Not using list_ prefix endpoint: get /accounts/search paginated: true # Explicitly enable paginationWhen you have multiple pagination schemes configured, Stainless will automatically match each endpoint to the appropriate scheme based on the request parameters and response fields. If you need to explicitly specify which pagination scheme a method should use, you can provide the scheme name as a string:
pagination: - name: cursor_page type: cursor # ... scheme configuration - name: offset_page type: offset # ... scheme configuration
resources: accounts: methods: list_accounts: endpoint: get /accounts paginated: cursor_page # Use the cursor_page scheme specifically list_transactions: endpoint: get /transactions paginated: offset_page # Use the offset_page scheme specificallyThis is especially useful when:
- Multiple pagination schemes could match an endpoint and you want to disambiguate
- You want to ensure a method uses a specific pagination scheme and get an error if it doesn’t match
- You have methods that don’t follow the
list_naming convention but are still paginated
Multiple pagination schemes
Section titled “Multiple pagination schemes”The pagination section accepts multiple pagination schemes. We match each endpoint against the defined
pagination schemes by making sure the relevant request parameters/response fields exist for that endpoint
and have the correct type.
In cases where it’s ambiguous or you want to explicitly assert that a method matches a specific pagination scheme, you can
provide paginated: <scheme_name> in the method configuration (e.g., paginated: my_offset_page), and the generator reports an error if it doesn’t match that specific page.
For more details on enabling pagination at the method level, see Enabling Pagination on Methods.
See the config reference for pagination for various examples and edge cases.
Other Pagination Properties
Section titled “Other Pagination Properties”Retrieving pagination properties from headers
Section titled “Retrieving pagination properties from headers”If your API returns pagination values in headers, you can use the from_header property to specify the header to read the value from.
pagination: - name: page_cursor_from_headers type: cursor request: ... response: my_cursor: type: string nullable: true x-stainless-pagination-property: purpose: next_cursor_field from_header: 'X-My-Cursor'Retrieving pagination properties from nested items
Section titled “Retrieving pagination properties from nested items”If your API returns pagination values nested within the response, you can configure Stainless to read them from the nested items.
Example response:
{ "data": { "items": [{}, {}] }, "pagination_object": { "next_page": "next_page_cursor", "previous_page": "previous_page_cursor" }}pagination: - name: page_cursor_nested_items type: cursor_id request: ... response: data: type: object properties: items: x-stainless-pagination-property: purpose: items type: array items: {} pagination_object: type: object properties: next_page: type: string x-stainless-pagination-property: purpose: next_cursor_id_param previous_page: type: string x-stainless-pagination-property: purpose: previous_cursor_id_paramTop level arrays in response
Section titled “Top level arrays in response”You can use the is_top_level_array property to indicate that the response is a top-level array.
Example response:
[ { "id": 1, "name": "Alice" }, { "id": 2, "name": "Bob" }]pagination: - name: top_level_array type: offset request: ... response: items: type: array items: {} x-stainless-pagination-property: is_top_level_array: true