Accounts v2
Open a bank account for a customer at the bank option you choose, follow it until it has bank details, and receive deposits.
API version: v2.
Use Accounts v2 to open a bank account for a customer. You choose the bank option, read what that bank needs, open the account in one call, and follow it until it has bank details. Each step has its own page, linked below.
A money example. Ada, a UK freelancer, wants to be paid 1,200.00 USD by a US client.
- Capabilities says which USD options a GB individual can open. You pick a wallet-backed one.
- Requirements lists the fields and documents that option needs.
POST /v2/accountsreturns{"account_id": "…", "status": "pending"}.- You wait for
applications.accounts.completed(Track activation), then read the account for its account and routing numbers. - The client sends 1,200.00 USD by ACH, and you see it with the deposit webhooks (Receive deposits).
The flow
flowchart LR
A[Customer KYC completed] --> B[GET /v1/accounts/capabilities]
B --> C[GET /v2/accounts/requirements]
C --> D[POST /v2/accounts]
D --> E{Account status}
E -- active --> F[Show bank details]
E -- pending, requires_user_action --> G[PATCH the application]
G --> E
E -- rejected or failed --> H[Choose another option]
Account and application
Opening a v2 account creates two records:
- The account (
id), which payers send money to once it isactive. - The application (
application_id), which tracks the bank's review. The create response does not include its id, so read it fromGET /v2/accounts/{id}.
Account statuses:
flowchart LR
pending --> active
pending --> rejected
pending --> failed
pending --> frozen
active --> frozen
frozen --> active
active --> closed
Application statuses:
| Status | Meaning |
|---|---|
processing |
The bank is working on the application |
blocked |
The application waits on you or the customer |
manual_review |
Gravv holds the application |
approved, rejected |
The final outcome, after the statuses above |
expired, cancelled |
These also end an application |
draft, submitted |
These appear only on applications not made with POST /v2/accounts |
What you can open
For any one customer, capabilities gives the current answer. Today, the options are:
| Currency | Wallet-backed (USDC behind the account) | Fiat-only (money stays in the currency) |
|---|---|---|
| USD | Available for individuals and businesses | Available for US residents and US companies, and for Kenya residents |
| EUR | Available | Available. One IBAN per customer, EUR or GBP |
| GBP | Available | Available. One IBAN per customer, EUR or GBP |
| NGN | Not supported | Available for Nigeria |
| KES, TZS, UGX | Not supported | Available for Kenya residents |
| CNY, RWF | Not supported | Not yet available |
| MXN, BRL, COP and others | Not supported | Not supported |
Each option excludes some countries. The lists change, so read excluded_countries from capabilities for each customer rather than storing them.
For a wallet-backed account, Gravv supports stellar, polygon, ethereum, avalanche_c_chain and solana. Send one of these that the option's token_options in requirements also lists. An option can list other networks too. Treat those as not supported. If in doubt, use polygon, which every wallet-backed option offers.
Before you start
- A customer whose
basicKYC iscompleted. Otherwise the API refuses the create call withCUSTOMER_KYC_INCOMPLETE. - If you use a scoped API key, it needs
account:createfor create and PATCH. - A webhook URL for
applications.accounts.*events, or a plan to pollGET /v2/accounts/{id}.
Pages
Read which banks, currencies, networks and rails a customer can have.
Get the fields and documents a bank needs, and turn them into a request.
Send one POST /v2/accounts and read the errors it can return.
Follow the application with webhooks or by reading the account.
Send the documents or data the bank asked for, or the customer's link.
List accounts with filters, and read balances and the bank details to give payers.
Read the deposit webhooks for fiat-only and wallet-backed accounts.
Simulate a deposit and learn what sandbox cannot do.