Skip to main content

Creating accounts

Open the account a card will spend from.

Before you begin​

  • A cardholder — see cardholders and KYC.
  • The program_id of the product you are opening the account under. GET /v1/programs returns the ids you may use; Settings → Programs in Cockpit shows the same list for reading by hand. Most organizations hold one.
  • A currency the program supports. Nothing here rejects an unsupported one on our side — it is refused when the account is opened at the processor — so check with your account contact if you are unsure which are available.

How it works​

An account holds value in exactly one currency, belongs to exactly one cardholder and exactly one program, and is what its card spends from.

program_id is where a program is named. Everything drawn on the account inherits it — the cards, and the authorizations and transactions those cards produce — so no call on the account's own path asks you for it again. It is fixed at creation: there is no call that moves an account to another program.

Send it even if you hold a single program. We could default to it, and that would be right until the day a second product went live, after which accounts would quietly open under the wrong one.

It opens active, with all three balances at zero:

ledger_balance 0 money that has settled
held_balance 0 reserved by authorizations that have not cleared
available_balance 0 ledger − held, the spendable figure

A cardholder who needs two currencies needs two accounts, and the API never converts between them.

Steps​

1. Create the account​

Call Create an account. The request names the program_id, the cardholder_id, the currency and, if you have one, your own reference. Send an Idempotency-Key so a retry doesn't open a second account.

The response is the account: active, in the currency you sent, with all three balances at zero.

2. Set reference while you are here​

reference is your own identifier. It is filterable, and it appears in every webhook payload for this account — which is what turns an incoming account.funded event into a row you can find in your own database without keeping a lookup table. List accounts takes it as a filter.

Retrofitting it later means backfilling every account you have already created. Set it now.

Verifying​

Read the account back with Get an account, or list the cardholder's accounts with List accounts.

You should see status: "active", the program_id you sent, and three zero balances. account.created fires on your webhook endpoint.

The list takes a program_id filter too, which is the shape to reach for if you run more than one product. Omit it and the page spans every program your organization holds — one credential covers all of them.

Common errors​

StatuscodeFix
400missing_parameterprogram_id was not sent. It is required even when you hold one program
400invalid_parameterprogram_id is malformed, or is not a program your organization holds. The two read the same on purpose — the API will not confirm that an id it refused exists somewhere else
404cardholder_not_foundcardholder_id is wrong, or belongs to another organization. The two are deliberately indistinguishable
409idempotency_key_reuseSame Idempotency-Key, different body — usually a bug in retry logic
422program_not_provisionedThe program is real and yours, but cannot serve this request. A configuration matter on our side — raise it rather than retrying

Note what is not in that list: there is no kyc_not_approved. That error belongs to issuing and activating a card, not account creation.