Key types
Publishable keys work on live rates (
GET /v1/rates), the activity feed (GET /v1/activity),
your fee schedule (GET /v1/developer-fees), and revenue reports (GET /v1/revenue,
GET /v1/reports/revenue). Every other endpoint — including all other reads — requires a secret
key and returns 403 secret_key_required when called with a publishable key.
Tenant binding
Every API key belongs to one tenant account. Its requests can read and change only that account’s customers, wallet, configuration, webhooks, and reporting. Create and store credentials separately for every tenant account. Choose the credential before making a request; the key determines the account for every Treasury call. Never reuse an idempotency key across separate credential stores.Roles
Each key is bound to a role that scopes what it can do. Reads are available to your role’s scope. Value-affecting writes — creating a customer, a payment route, or a webhook subscription, or submitting a Treasury wallet operation — require a secret key with write access. API key creation, rotation, restriction, and revocation additionally require a recent second-factor (MFA) confirmation, so manage keys from the console (Developers → API keys). A key-management request authenticated only with an API key returns403 step_up_required.
Scopes and key restrictions
Scopes are optional, per-key restrictions granted per resource family. The families arecustomers, routes, transfers, treasury, webhooks, fees, keys, team, and
settings, each with :read and :write, plus rates:read. Within a family,
<family>:write implies <family>:read.
team:write (inviting a teammate) is a credential-issuing action, like API key management
above — it always requires a signed-in console admin with a fresh second factor, so a bare API
key can hold the scope but can never satisfy the request on its own.
A key created without a scope list keeps its full role-implied access. A scoped key can call only
endpoints in the families it holds, so include every family your integration uses — for example
rates:read if you fetch live rates, as in the example below. A request outside a scoped key’s
grants returns 403 insufficient_scope, and the error message names the scope the route requires.
Treasury scopes
Network binding
A key may optionally carry anallowedIps list of IP addresses or CIDR blocks (IPv4 or IPv6; a
bare address means a single host). Set it at key creation or rotation, or via
PATCH /v1/api-keys/{id} — passing null clears the restriction, and a rotated key inherits the
retiring key’s scopes and allowed IPs unless you override them.
Requests presented from outside those networks return 403 ip_not_allowed; a request whose source
network cannot be determined is also refused. Keys without allowedIps are callable from anywhere.
Direct-route transfers are recorded automatically when a customer funds a payment route. Treasury
is different: you create payouts, withdrawals and quoted wallet conversions against a prefunded
wallet owned only by the authenticated tenant account. See the Treasury
overview and API reference.
Example request
401. See Errors for the full error shape.
