Open a fiat-only USD account in the US
Open a USD account at a US bank for a US resident or a US company, with no stablecoin, so deposits stay in dollars.
Open a USD account at a US bank for a US resident or a US company, with no stablecoin. Deposits stay in dollars.
API version: v2.
Who it is for. A US payroll platform that holds the dollars of employees and small US businesses at a US bank, without any stablecoin.
Status. Available for US residents and US-incorporated businesses. For anyone else, fiat-only USD is Not supported, except in Kenya.
Money example
Rocky Mountain Bakery LLC in Denver receives 3,200.00 USD from a catering client.
- The client pays 3,200.00 USD by ACH to the account and routing number.
- The bank credits 3,200.00 USD. Gravv books the deposit and sends
transfer.inflow.completed. Gravv converts nothing. - The account's balance is the bank's own figure (
balance_sourceinstitution).
Before you start
- The customer's
basicKYC iscompleted. For a business, every associated person's KYC iscompletedfirst. - The customer is a US resident (
citizenship_countryUS) or a US company (incorporation_countryUS). Capabilities withcountry=USshow a USD option withtoken_wallets: []. Sandbox lists this option for customers in other countries too, so do not rely on capabilities to stop a non-US customer. - The option usually allows one account per customer. Check
max_accounts_per_customer.
Find out what is required
Read requirements with the option's bank_code and country=US.
| A person | A business | |
|---|---|---|
| Always | Names, date_of_birth, email, phone_daytime, citizenship_country, permanent_address, employment_status, and expected_activity (expected_avg_daily_balance, ach_in.monthly_count, ach_in.monthly_amount) |
legal_name, email, registration_number, incorporation_country, incorporation_date, tax_id_type (ein in the US), tax_id_number, industry (from its options), business_status, business_entity_type, business_address, expected_activity |
| When it applies | employer_info when employed. income_source with no employer. tax_id_type (ssn for a US citizen) and tax_id_number |
corporation_taxed_as for a corporation. llc_taxed_as for an llc |
| Parties | None | 1 to 10, each with names, email, party_role (primary, authorized_individual, …), date_of_birth, citizenship_country, permanent_address and mailing_address. A party with ownership also needs ownership_percentage. A US citizen also needs tax_id_type ssn and tax_id_number |
| Documents | One identity document and proof_of_address |
articles_of_incorporation, ownership_document, proof_of_address and control_structure, plus one identity document per party |
The API refuses P.O. Box addresses. The form also has rules for non-US persons, such as a W-8BEN tax form. Those rules apply only to non-US citizens or companies.
Steps
1. Open the account, with no network
curl --request POST \
--url https://api.gravv.xyz/v2/accounts \
--header 'Api-Key: <API_KEY>' \
--header 'Idempotency-Key: d309b5ae-0a87-423a-aae0-2411d53100c8' \
--header 'Content-Type: application/json' \
--data '
{
"customer_id": "4b7d1e2a-9c3f-4a5b-8d6e-0f1a2b3c4d5e",
"customer_type": "business",
"currency": "USD",
"account_type": "operating",
"category": "sub_account",
"bank_code": "<bank_code>",
"label": "Rocky Mountain Bakery USD",
"data": {
"root": {
"legal_name": "Rocky Mountain Bakery LLC",
"email": "accounts@rockymountainbakery.example",
"registration_number": "20151234567",
"incorporation_country": "US",
"incorporation_date": "2015-06-01",
"tax_id_type": "ein",
"tax_id_number": "841234567",
"industry": "manufacturing",
"business_status": "operating",
"business_entity_type": "llc",
"llc_taxed_as": "partnership",
"business_address": {"address_line": "1600 Pearl Street", "city": "Denver", "state": "US-CO", "postal_code": "80202", "country": "US"},
"expected_activity": {"expected_avg_daily_balance": 25000, "ach_in": {"monthly_count": 40, "monthly_amount": 60000}}
},
"parties": [
{
"id": "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b",
"party_role": "primary",
"date_of_birth": "1984-11-02",
"citizenship_country": "US",
"has_ownership": true,
"ownership_percentage": 100,
"tax_id_type": "ssn",
"tax_id_number": "123456780",
"permanent_address": {"address_line": "88 Elm Avenue", "city": "Denver", "state": "US-CO", "postal_code": "80203", "country": "US"},
"mailing_address": {"address_line": "88 Elm Avenue", "city": "Denver", "state": "US-CO", "postal_code": "80203", "country": "US"},
"documents": [
{"document_type": "drivers_license", "document_type_side": "front", "issuing_country": "US", "number": "D1234567", "issued_date": "2022-04-10", "expiration_date": "2030-04-10", "filename": "dl-front.jpg", "content": "<base64>"}
]
}
],
"documents": [
{"document_type": "articles_of_incorporation", "issuing_country": "US", "filename": "articles.pdf", "content": "<base64>"},
{"document_type": "ownership_document", "issuing_country": "US", "filename": "operating-agreement.pdf", "content": "<base64>"},
{"document_type": "proof_of_address", "issuing_country": "US", "filename": "lease.pdf", "content": "<base64>"},
{"document_type": "control_structure", "issuing_country": "US", "filename": "control.pdf", "content": "<base64>"}
]
}
}
'
const response = await fetch("https://api.gravv.xyz/v2/accounts", {
method: "POST",
headers: {
"Api-Key": process.env.GRAVV_API_KEY,
"Idempotency-Key": "d309b5ae-0a87-423a-aae0-2411d53100c8",
"Content-Type": "application/json",
},
body: JSON.stringify({
"customer_id": "4b7d1e2a-9c3f-4a5b-8d6e-0f1a2b3c4d5e",
"customer_type": "business",
"currency": "USD",
"account_type": "operating",
"category": "sub_account",
"bank_code": "<bank_code>",
"label": "Rocky Mountain Bakery USD",
"data": {
"root": {
"legal_name": "Rocky Mountain Bakery LLC",
"email": "accounts@rockymountainbakery.example",
"registration_number": "20151234567",
"incorporation_country": "US",
"incorporation_date": "2015-06-01",
"tax_id_type": "ein",
"tax_id_number": "841234567",
"industry": "manufacturing",
"business_status": "operating",
"business_entity_type": "llc",
"llc_taxed_as": "partnership",
"business_address": {
"address_line": "1600 Pearl Street",
"city": "Denver",
"state": "US-CO",
"postal_code": "80202",
"country": "US"
},
"expected_activity": {
"expected_avg_daily_balance": 25000,
"ach_in": {
"monthly_count": 40,
"monthly_amount": 60000
}
}
},
"parties": [
{
"id": "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b",
"party_role": "primary",
"date_of_birth": "1984-11-02",
"citizenship_country": "US",
"has_ownership": true,
"ownership_percentage": 100,
"tax_id_type": "ssn",
"tax_id_number": "123456780",
"permanent_address": {
"address_line": "88 Elm Avenue",
"city": "Denver",
"state": "US-CO",
"postal_code": "80203",
"country": "US"
},
"mailing_address": {
"address_line": "88 Elm Avenue",
"city": "Denver",
"state": "US-CO",
"postal_code": "80203",
"country": "US"
},
"documents": [
{
"document_type": "drivers_license",
"document_type_side": "front",
"issuing_country": "US",
"number": "D1234567",
"issued_date": "2022-04-10",
"expiration_date": "2030-04-10",
"filename": "dl-front.jpg",
"content": "<base64>"
}
]
}
],
"documents": [
{
"document_type": "articles_of_incorporation",
"issuing_country": "US",
"filename": "articles.pdf",
"content": "<base64>"
},
{
"document_type": "ownership_document",
"issuing_country": "US",
"filename": "operating-agreement.pdf",
"content": "<base64>"
},
{
"document_type": "proof_of_address",
"issuing_country": "US",
"filename": "lease.pdf",
"content": "<base64>"
},
{
"document_type": "control_structure",
"issuing_country": "US",
"filename": "control.pdf",
"content": "<base64>"
}
]
}
}),
});
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": "d309b5ae-0a87-423a-aae0-2411d53100c8",
"Content-Type": "application/json",
},
json={
"customer_id": "4b7d1e2a-9c3f-4a5b-8d6e-0f1a2b3c4d5e",
"customer_type": "business",
"currency": "USD",
"account_type": "operating",
"category": "sub_account",
"bank_code": "<bank_code>",
"label": "Rocky Mountain Bakery USD",
"data": {
"root": {
"legal_name": "Rocky Mountain Bakery LLC",
"email": "accounts@rockymountainbakery.example",
"registration_number": "20151234567",
"incorporation_country": "US",
"incorporation_date": "2015-06-01",
"tax_id_type": "ein",
"tax_id_number": "841234567",
"industry": "manufacturing",
"business_status": "operating",
"business_entity_type": "llc",
"llc_taxed_as": "partnership",
"business_address": {
"address_line": "1600 Pearl Street",
"city": "Denver",
"state": "US-CO",
"postal_code": "80202",
"country": "US",
},
"expected_activity": {
"expected_avg_daily_balance": 25000,
"ach_in": {
"monthly_count": 40,
"monthly_amount": 60000,
},
},
},
"parties": [
{
"id": "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b",
"party_role": "primary",
"date_of_birth": "1984-11-02",
"citizenship_country": "US",
"has_ownership": True,
"ownership_percentage": 100,
"tax_id_type": "ssn",
"tax_id_number": "123456780",
"permanent_address": {
"address_line": "88 Elm Avenue",
"city": "Denver",
"state": "US-CO",
"postal_code": "80203",
"country": "US",
},
"mailing_address": {
"address_line": "88 Elm Avenue",
"city": "Denver",
"state": "US-CO",
"postal_code": "80203",
"country": "US",
},
"documents": [
{
"document_type": "drivers_license",
"document_type_side": "front",
"issuing_country": "US",
"number": "D1234567",
"issued_date": "2022-04-10",
"expiration_date": "2030-04-10",
"filename": "dl-front.jpg",
"content": "<base64>",
},
],
},
],
"documents": [
{
"document_type": "articles_of_incorporation",
"issuing_country": "US",
"filename": "articles.pdf",
"content": "<base64>",
},
{
"document_type": "ownership_document",
"issuing_country": "US",
"filename": "operating-agreement.pdf",
"content": "<base64>",
},
{
"document_type": "proof_of_address",
"issuing_country": "US",
"filename": "lease.pdf",
"content": "<base64>",
},
{
"document_type": "control_structure",
"issuing_country": "US",
"filename": "control.pdf",
"content": "<base64>",
},
],
},
},
)
print(response.status_code, response.json())
The API returns {"account_id": "…", "status": "pending"}.
2. Follow it until it is active
Read GET /v2/accounts/{id}, or wait for applications.accounts.completed, as in the wallet-backed recipe. If the application stops, see Unblock an application.
3. Give the details to the payer
Follow Share account details and receive a deposit. In live, this option's account does not return virtual_account_bank_name or _bank_address yet, so show the account's bank_name. Returning those fields is Not yet available.
What can go wrong
Every error in the wallet-backed recipes that does not concern the network can happen here too. These errors are specific to this option:
| Response | Why | Fix |
|---|---|---|
400 network is only accepted for account options that support wallet integration |
You sent network to a fiat-only option |
Remove it |
400 bank_code=<code> does not open accounts for customers resident in GB. … (COUNTRY_NOT_SERVED) |
The customer is not a US customer | Open a wallet-backed USD account |
409 this customer already holds the maximum number of USD accounts permitted for this account type (1) |
The option allows one account per customer | Use the existing account |
400 details.tax_id_type: guard_violation: must be ein when incorporation_country is US |
A US company sent tin |
Send ein |
400 details.party[0].tax_id_type: guard_violation: must be ssn when citizenship_country is US |
A US-citizen party sent tin |
Send ssn |
400 details.industry: invalid_enum: … |
The value is not in the list | Send one of the field's options, such as manufacturing |
400 details.llc_taxed_as: required: is required |
An llc has no tax class |
Send c_corp, s_corp or partnership |
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 calls the bank's own test system, so activation is not instant. Simulate deposits with rail ach or wire. See Test accounts with a simulated deposit.