Adding pagination to Your SDK

In SDKs managed by Speakeasy, you can customize pagination rules for each API operation using the x-speakeasy-pagination OpenAPI extension.

Adding pagination to your SDK improves your SDK users' developer experience. If your API is paginated, Speakeasy provides an iterable object that users can loop over. For end users, this means an experience that resembles the following:

response = sdk.paginatedEndpoint(page=1)
while response is not None:
    # handle response
    
    response = response.next()

Note: The next() function returns nil, nil when the pages are exhausted to differentiate from an error case.

Configuring Pagination

  /paginated/endpoint:
    get:
      parameters:
        - name: page
          in: query
          schema:
            type: integer
          required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                title: res
                type: object
                properties:
                  resultArray:
                    type: array
                    items:
                      type: integer
                required:
                  - resultArray
      x-speakeasy-pagination:
        type: offsetLimit
        inputs:
          - name: page
            in: parameters
            type: page
        outputs:
          results: $.resultArray

The x-speakeasy-pagination configuration supports both offsetLimit and cursor implementations of pagination.

Offset and Limit Pagination

When you specify type: offsetLimit in the pagination configuration, you need to configure at least one of the following inputs: offset or page.

Example inputs.page Configurations

x-speakeasy-pagination:
  type: offsetLimit
  inputs:
    - name: page                  # This input refers to the value called `page`
      in: parameters              # In this case, page is an operation parameter (header, query, or path)
      type: page                  # The page parameter will be used as the page-value for pagination, and will be incremented when `next()` is called
    - name: limit                 # This input refers to the value called `limit`
      in: parameters              # In this case, limit is an operation parameter (header, query, or path)
      type: limit                 # The limit parameter will be used as the limit-value for pagination
  outputs:
    results: $.data.resultArray   # The data.resultsArray value of the response will be used to infer whether there is another page

In this example, at least one response object must have the following structure:

{
  "data": {
    "resultArray": []
  }
}

Because inputs.limit is defined in the pagination configuration above, next() will return null when $.data.resultArray has a length less than the value provided as inputs.limit. If inputs.limit is omitted, next() will return null when the length of $.data.resultArray is equal to 0.

If you use the page input, you can use output.numPages instead of output.results to determine when the pages for the operation are exhausted.

x-speakeasy-pagination:
  type: offsetLimit
  inputs:
    - name: page                # This input refers to the value called `page`
      in: parameters            # In this case, page is an operation parameter (header, query, or path)
      type: page                # The page parameter will be used as the page, and will be incremented when `next()` is called
  outputs:
    numPages: $.data.numPages   # The data.numPages value of the response will be used to infer whether there is another page

If you provide the numPages output, next() returns null when the incremented page number is greater than the numPages value.

In the above example, at least one response object must have the following structure:

{
  "data": {
    "numPages": 1
  }
}

Example inputs.offset Configuration

x-speakeasy-pagination:
  type: offsetLimit
  inputs:
    - name: offset                # This offset refers to the value called `offset`
      in: parameters              # In this case, offset is an operation parameter (header, query, or path)
      type: offset                # The offset parameter will be used as the offset, which will be incremented by the length of the `output.results` array
  outputs:
    results: $.data.resultArray   # The length of data.resultsArray value of the response will be added to the `offset` value to determine the new offset

Note: In this example, inputs.limit has the same effect as in the inputs.page example.

Cursor-Based Pagination

When you specify type: cursor in the pagination configuration, you need to configure the nextCursor output.

Example inputs.cursor Configuration

x-speakeasy-pagination:
  type: cursor
  inputs:
    - name: since
      in: requestBody
      type: cursor
  outputs:
    nextCursor: $.data.resultArray[(@length-1)].created_at   

Because the input above is in the requestBody, this operation must take a request body with at least the following structure:

{
  "since": ""
}

In the above example, at least one response object must have the following structure:

{
  "data": {
    "resultArray": [
      {
        "created_at": ""
      }
    ]
  }
}

Note: The [@length-1)] syntax in outputs.nextCursor indicates the last value in an array.

Note: The type of requestBody.since must correspond to the type of outputs.nextCursor.

Inputs

name

With in: parameters, this is the name of the parameter to use as the input value.

With in: requestBody, this is the name of the request-body property to use as the input value.

in

Indicates whether the input should be passed into the operation as a path or query parameter (in: parameters) or in the request-body (in: requestBody). Only simple objects are permitted as values in the request-body.

type

TypeDescription
pageThe variable that will be incremented on calling next().
offsetThe variable that will be incremented by the number of results returned by the previous execution. Note: Requires outputs.Results.
limitWhen provided, next() returns null (or equivalent) when the number of results returned by the previous execution is less than the value provided.

Outputs

All of the outputs are expected to be strings adhering to the JSONPath (opens in a new tab) schema.

KeyDescription
numPagesWhen provided, next() returns null if the page input value exceeds the value found at the provided JSON path. Note: Requires page input.
resultsWhen provided, next() returns null if the array found at the provided JSON path is empty. Note: Required by offset input.
nextCursorPopulates cursor with the value found at the provided JSON path when calling next(). Note: Required by type: cursor.

Note: If the JSONPath value provided for an output does not match the response returned, next() returns null because pagination cannot be continued.