Skip to main content
These conventions apply to every endpoint.

Requests and responses

  • Request and response bodies are JSON, with Content-Type: application/json. Field names are snake_case.
  • Every response carries a Request-Id header (req_ followed by 16 characters). Log it; support uses it to find the request.
  • Unknown fields and query parameters are rejected with 400 unknown_parameter, naming the first one in param. Strict parsing turns a typo such as payeeId into an immediate error instead of a silently ignored field.

Object IDs

IDs are opaque strings: a prefix naming the object type, followed by 16 random lowercase characters. IDs are random, so they reveal nothing about volume or ordering. Don’t parse them, construct them or rely on their length; store them as strings of up to 64 characters. IDs are unique within an environment, and sandbox IDs never resolve in live.

Amounts

Amounts are decimal strings, for example "500.00".
  • An amount may carry at most the currency’s number of decimals, which GET /currencies reports as decimals. "500.001" in EUR is rejected.
  • A JSON number such as 500 is rejected with 400 type_mismatch. Strings keep amounts exact in every language, where floating-point numbers can silently lose precision.
  • Amounts in responses always carry the currency’s full decimals: "500.00", never "500".
  • Exchange rates are decimal strings too, for example "0.8955".

Currencies and countries

An uppercase currency code such as "EUR" is rejected.

Timestamps

Timestamps are ISO 8601 strings in UTC, for example "2026-10-26T10:05:00Z". Use the same format in query filters such as created[gte].

Nulls

Every documented field is always present in responses. A field with no value is null, and an empty metadata is {}, so the shape of an object never varies.

Reference, metadata and description

Payees, batches and payouts accept your own data, which is returned on every read and in every event: Don’t store sensitive personal data in reference or metadata.

Pagination

List endpoints use cursor-based pagination and return the newest objects first:
To read every page, pass the last ID of each page as starting_after until has_more is false:
Cursors stay stable as new objects are created, so paging through a busy list never skips or repeats an object. Lists that are always short return everything with has_more: false and take no paging parameters: wallets, funding addresses, currencies, bank requirements, a payee’s addresses and webhook endpoints.