Pagination

Pagination style varies by API and version:

APIStyleCollection keyNext page
Contracting & Hierarchies API v2Tokenitemspage.nextTokenpage_token param
Identity API (v2)Tokenitemspage.nextTokenpage_token param
ProducerSync API v2Continuation tokenembeddedlinks.next.href

v2 Token Pagination — Contracting, Hierarchies & Identity

All v2 list endpoints share one envelope: results in a top-level items array, pagination metadata in page.

{
  "items": [ { ... }, { ... } ],
  "page": {
    "size": 25,
    "nextToken": "eyJ2IjoxLCJrIjp7Li4ufX0"
  }
}
FieldDescription
itemsThe page of results. Empty array when nothing matches.
page.sizeNumber of items actually returned in this response — equal to items.length, so an empty result reports 0.
page.nextTokenOpaque token for the next page, or null on the last page. The token format is server-controlled — never parse or construct it.

Query parameters:

ParameterDescription
page_tokenThe previous response's page.nextToken. Omit on the first request.
page_sizeRequested items per page. Defaults to 25 on all v2 endpoints.

The request parameter and the response field have different names. You read the token out of page.nextToken and send it back as page_token — there is no nextToken query parameter. Response bodies are camelCase; query parameters are lower_snake_case. See Data Formats and Field Types.

Page size limits: page_size must be between 1 and 250 on Contracting, Hierarchies and Identity alike. Out-of-range values are rejected with a 400 rather than clamped, so you get an explicit error instead of a silently truncated page.

Read page.size back off the response rather than assuming it equals what you asked for: page.size is the number of items actually returned, so it is smaller than your requested size on the last page and 0 on an empty result.

Walking from the first page to the second:

# First request — no token.
curl -H "Authorization: Bearer $ACCESS_TOKEN" \
  "https://api.sandbox.agentsync.io/contracting/v2/producers?page_size=25"
{
  "items": [ { ... } ],
  "page": {
    "size": 25,
    "nextToken": "eyJ2IjoxLCJrIjp7ImlkIjoiMDBiNjc5NWUtYmNmNS0xNDZhLWEzMGYtYmI4NTk0MzBhMTk5In19"
  }
}
# Second request — the value of page.nextToken, sent as page_token.
curl -H "Authorization: Bearer $ACCESS_TOKEN" \
  "https://api.sandbox.agentsync.io/contracting/v2/producers?page_size=25&page_token=eyJ2IjoxLCJrIjp7ImlkIjoiMDBiNjc5NWUtYmNmNS0xNDZhLWEzMGYtYmI4NTk0MzBhMTk5In19"

Keep page_size (and any filters) identical across every request in a run. Repeat until page.nextToken is null.

Troubleshooting: the same page keeps coming back

Check the parameter name first. Only page_token advances the page — nextToken, next_token, and pageToken are all ignored, and unrecognized parameters are dropped rather than rejected. So the wrong name returns 200 with the first page every time, not an error.

A 400 actually tells you the opposite: the name was right and the token couldn't be decoded. Send the token back exactly as received — it is opaque and URL-safe, so it needs no encoding, trimming, or base64 decoding.

Iterating all pages (Python):

def paginate_v2(access_token, base_url, path, params=None):
    """Fetch every item from a v2 token-paginated list endpoint."""
    items = []
    params = dict(params or {})

    while True:
        response = requests.get(
            f"{base_url}{path}",
            headers={"Authorization": f"Bearer {access_token}"},
            params=params,
        )
        response.raise_for_status()
        data = response.json()
        items.extend(data["items"])

        next_token = data["page"]["nextToken"]
        if next_token is None:
            return items
        params["page_token"] = next_token

No totals by design. v2 responses do not include totalElements or totalPages — iterate until nextToken is null. A pagination run is not a point-in-time snapshot: records updated mid-run may first appear on a later poll.


ProducerSync API v2 — Continuation Token Pagination

ProducerSync v2 endpoints paginate with continuation tokens carried in a links object.

First Page

Your initial request returns:

  • a set of results under the embedded key
  • a links object, including a next URL for retrieving the next page

Note: The ProducerSync API uses embedded and links, which differs from the items envelope used by Contracting, Hierarchies, and Identity. If you integrate multiple APIs, handle each collection key separately.

Example Response:

{
  "embedded": {
    "licenses": [
      { ... },
      { ... }
    ]
  },
  "links": {
    "self": {
      "href": "https://api.agentsync.io/v2/licenses?continuationToken=0"
    },
    "next": {
      "href": "https://api.agentsync.io/v2/licenses?continuationToken=11862929"
    }
  }
}

Iterating with links.next

Follow the URL in links.next.href until the end of the dataset:

GET https://api.agentsync.io/v2/licenses?continuationToken=11862929

End of Results

On the final page:

  • the response will NOT include an embedded object
  • links.next.href will include continuationToken=0
{
  "links": {
    "self": {
      "href": "https://api.agentsync.io/v2/licenses?continuationToken=11862929"
    },
    "next": {
      "href": "https://api.agentsync.io/v2/licenses?continuationToken=0"
    }
  }
}

A query with no results at all returns the same shape — no embedded key and continuationToken=0 on both links. Handle this case gracefully.

Controlling Page Size

Pass size to control results per page (default 250):

  • Minimum: 1
  • Maximum: 1000
GET /v2/licenses?size=500