Skip to content

API fundamentals

Pagination

Walk through lists of payments, refunds and events with cursors.

Every endpoint that returns a collection, GET /payments, GET /refunds and GET /events, uses the same cursor-based pagination. Results come newest first.

The list envelope

{
  "object": "list",
  "data": [
    { "id": "5b1c2f4e-9d3a-4c61-8a7e-0f2d6b9e1a33", "object": "payment", "status": "paid" }
  ],
  "has_more": true,
  "next_cursor": "5b1c2f4e-9d3a-4c61-8a7e-0f2d6b9e1a33"
}
objectstring

Always list.

dataarray

The objects of this page.

has_moreboolean

true when older objects remain.

next_cursorstringnullable

Pass it as starting_after to get the next page. null on the last page.

Parameters

limitinteger

How many objects to return, from 1 to 100. Defaults to 20.

starting_afterstring

The cursor of the page to return, which is the next_cursor of the previous page (the id of its last object).

A cursor that is not the id of an object of your store answers 400 with invalid_cursor. A cursor that is not a valid id does too. A limit below 1 or above 100 answers 400 with parameter_out_of_range.

Walk through every page

curl 'https://api.rais.app/v1/payments?limit=2' \
  -H "Authorization: Bearer rais_sk_test_..."

Send the first request without a cursor. While has_more is true, send the next one with starting_after set to next_cursor.

async function* allPayments(query = "") {
  let cursor = null;
  do {
    const url = new URL("https://api.rais.app/v1/payments");
    url.searchParams.set("limit", "100");
    if (cursor) url.searchParams.set("starting_after", cursor);
    for (const [key, value] of new URLSearchParams(query)) url.searchParams.set(key, value);

    const response = await fetch(url, { headers: { Authorization: `Bearer ${process.env.RAIS_SECRET_KEY}` } });
    const page = await response.json();
    yield* page.data;
    cursor = page.has_more ? page.next_cursor : null;
  } while (cursor);
}

for await (const payment of allPayments("status=paid")) console.log(payment.id);
import os
import requests

def all_payments(**filters):
    cursor = None
    while True:
        params = {"limit": 100, **filters}
        if cursor:
            params["starting_after"] = cursor
        page = requests.get(
            "https://api.rais.app/v1/payments",
            params=params,
            headers={"Authorization": f"Bearer {os.environ['RAIS_SECRET_KEY']}"},
            timeout=30,
        ).json()
        yield from page["data"]
        if not page["has_more"]:
            return
        cursor = page["next_cursor"]

for payment in all_payments(status="paid"):
    print(payment["id"])

Good to know

  • Pages are stable: new objects appear at the start of the list and never shift the pages you are still walking through.
  • Filters work with pagination. For payments: status, reference, created_gte and created_lte (Unix seconds). For refunds: payment. For events: type. A filter with an invalid value answers 400 invalid_parameter, but a parameter the API does not know is ignored: ?stauts=paid returns the unfiltered list.
  • Events can be listed for 30 days only.
  • Pass the cursor exactly as received. Do not build one yourself.