Skip to content

List endpoints in the Rho API return results in pages using opaque cursor-based pagination. You ask for a page size, the response includes the items plus a cursor to the next page, and you follow that cursor to fetch each subsequent page.

Cursors are stable across changes to the underlying data: new items inserted while you are iterating will not shift existing pages or cause items to be skipped or duplicated.

Request parameters

Every list endpoint accepts the same two pagination parameters as query string values:

ParameterTypeNotes
page_sizeintegerHow many items to return. Each endpoint defines its own minimum, maximum, and default - see the API Reference. Values outside the allowed range return 400 Bad Request.
page_tokenstringOpaque cursor returned as next_page_token by a previous response. Omit to fetch the first page.

Cursors are opaque - pass back exactly the string you received.

A token returned by one endpoint is only valid for that same endpoint with the same filters and sort order. Using a cursor with changed filters or sorting will result in 400 Bad Request.

Response shape

Every paginated response wraps the items in a top-level array and includes a page object:

{
  "transactions": [
    { "id": "…", "amount": { "amount": 1299, "currency": "USD" }, "…": "…" },
    { "id": "…", "amount": { "amount": 4500, "currency": "USD" }, "…": "…" }
  ],
  "page": {
    "next_page_token": "eyJvIjoxMDAsImQiOiIyMDI2LTA1LTE0In0"
  }
}

The array key matches the resource being listed (accounts, transactions, …). The page.next_page_token field is either:

  • A string - pass it as page_token on the next request to fetch the following page.
  • null - you have reached the last page; there is nothing more to fetch.

Walking through every page

The canonical iteration pattern is a loop that stops when the cursor goes null. In Python:

import os
import requests

def list_all_transactions(account_id: str):
    token = os.environ["RHO_API_TOKEN"]
    page_token = None
    while True:
        params = {"account_id": account_id, "page_size": 100}
        if page_token is not None:
            params["page_token"] = page_token

        resp = requests.get(
            "https://rhoapi.rho.co/api/v1/transactions",
            params=params,
            headers={"Authorization": f"Bearer {token}"},
            timeout=30,
        )
        resp.raise_for_status()
        body = resp.json()

        yield from body["transactions"]

        page_token = body["page"]["next_page_token"]
        if page_token is None:
            return

Equivalent with curl:

# First page
curl "https://rhoapi.rho.co/api/v1/transactions?page_size=100" \
  -H "Authorization: Bearer $RHO_API_TOKEN"

# Subsequent page - pass the next_page_token from the previous response
curl "https://rhoapi.rho.co/api/v1/transactions?page_size=100&page_token=eyJvIjoxMDAsImQiOiIyMDI2LTA1LTE0In0" \
  -H "Authorization: Bearer $RHO_API_TOKEN"

Common mistakes

  • Modifying filters between pages. A page_token is bound to the query it was issued for. Change account_id, status, sort_by, etc., and you must start over from the first page.
  • Storing cursors long-term. Cursors are designed for live iteration, not for bookmarks. Their format and lifetime are not part of the API contract and may change without notice.