Open an account held in Kenya
Open a KES, TZS, UGX, USD, EUR or GBP account at a Kenyan bank for a customer resident or incorporated in Kenya.
Open a KES, TZS, UGX, USD, EUR or GBP account at a Kenyan bank for a customer who is resident or incorporated in Kenya.
API version: v2.
Who it is for. A Nairobi import business that wants a KES operating account and a USD account at a Kenyan bank to pay suppliers.
Status. Available for customers in Kenya in KES, TZS, UGX, USD, EUR and GBP. CNY and RWF are Not yet available. These accounts are fiat-only and have no wallet.
Money example
Savanna Traders Ltd receives 650,000.00 KES from a buyer.
- The buyer transfers 650,000.00 KES to the account number at the named bank.
- The bank credits the deposit. Gravv sends
transfer.inflow.completedwithcurrencyKES.
Before you start
- The customer's
basicKYC iscompleted, and the customer is resident or incorporated in Kenya. Sandbox lists this option for other countries too, so check the country yourself. - Capabilities with
country=KE¤cy=KESlist the option. Itsrailscan be[]. If so, ask support which local rails payers can use before you promise them.
Find out what is required
Read requirements with country=KE. The form is short:
| A person | A business | |
|---|---|---|
| Fields | first_name and last_name. Gravv fills both from the customer if you leave them out |
legal_name. Gravv fills it from the customer if you leave it out |
| Parties, documents | None | None |
Steps
1. Open the account
curl --request POST \
--url https://api.gravv.xyz/v2/accounts \
--header 'Api-Key: <API_KEY>' \
--header 'Idempotency-Key: 2de0aa93-f75b-4ed4-a486-010cf885aca7' \
--header 'Content-Type: application/json' \
--data '
{
"customer_id": "8e9f0a1b-2c3d-4e5f-8a6b-7c8d9e0f1a2b",
"customer_type": "business",
"currency": "KES",
"account_type": "operating",
"category": "sub_account",
"bank_code": "<bank_code>",
"label": "Savanna KES",
"data": {
"root": {
"legal_name": "Savanna Traders Ltd",
"incorporation_country": "KE"
}
}
}
'
const response = await fetch("https://api.gravv.xyz/v2/accounts", {
method: "POST",
headers: {
"Api-Key": process.env.GRAVV_API_KEY,
"Idempotency-Key": "2de0aa93-f75b-4ed4-a486-010cf885aca7",
"Content-Type": "application/json",
},
body: JSON.stringify({
"customer_id": "8e9f0a1b-2c3d-4e5f-8a6b-7c8d9e0f1a2b",
"customer_type": "business",
"currency": "KES",
"account_type": "operating",
"category": "sub_account",
"bank_code": "<bank_code>",
"label": "Savanna KES",
"data": {
"root": {
"legal_name": "Savanna Traders Ltd",
"incorporation_country": "KE"
}
}
}),
});
console.log(response.status, await response.json());
import os
import requests
response = requests.post(
"https://api.gravv.xyz/v2/accounts",
headers={
"Api-Key": os.environ["GRAVV_API_KEY"],
"Idempotency-Key": "2de0aa93-f75b-4ed4-a486-010cf885aca7",
"Content-Type": "application/json",
},
json={
"customer_id": "8e9f0a1b-2c3d-4e5f-8a6b-7c8d9e0f1a2b",
"customer_type": "business",
"currency": "KES",
"account_type": "operating",
"category": "sub_account",
"bank_code": "<bank_code>",
"label": "Savanna KES",
"data": {
"root": {
"legal_name": "Savanna Traders Ltd",
"incorporation_country": "KE",
},
},
},
)
print(response.status_code, response.json())
The API returns {"account_id": "…", "status": "pending"}.
2. Read the account
Read GET /v2/accounts/{id} until the status is active. The payer needs virtual_account_bank_name and virtual_account_bank_account_number. These accounts have no routing number.
3. Add another currency
For a USD account at the same bank, send the same body with "currency": "USD" and a new key.
What can go wrong
| Response | Why | Fix |
|---|---|---|
400 bank_code=<code> does not open accounts for customers resident in UG. … |
The customer is not in Kenya | Use this option only for customers in Kenya |
400 network is only accepted for account options that support wallet integration |
You sent network |
Remove it |
400 details.<key>: unknown_field: is not a recognized field |
You misspelled a key | Fix the key name |
The option shows rails: [] |
Gravv publishes no incoming rails for it | Ask support before you promise a rail |
Webhooks you will receive
Gravv sends applications.accounts.* events until the account is active. For each deposit, Gravv sends transfer.inflow.completed.
Testing in sandbox
Sandbox has no simulator that opens this account. Sandbox calls the bank's test system, so activation is not instant. You can still simulate a deposit. Send no rail in the simulator request.