Why can't I create a virtual account?
The four gates on virtual-account creation, the error each one returns, and the exact fix.
Virtual-account creation is gated, and every gate returns a distinct code naming what to do. Work down this list in order.
1. 400 endorsement_required
The currency's endorsement was never requested. Enrollment is explicit:
a customer without endo_usd never reaches USD verification at all.
curl -s -X PATCH $BASE/api/customers/cus_... \
-H "Api-Key: $KEY" -H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"endorsements": ["endo_usd"]}'
If the customer is missing the profile fields endo_usd needs, this PATCH
returns 422 endorsement_profile_required instead. Send email, phone,
economic_profile.tin, and economic_profile.tax_residence_country in the
same request.
2. 400 endorsement_not_approved
It was requested, but it is not approved yet. The message names the current
status, and the customer's endorsements[].requirements buckets name
everything still outstanding.
missingitems: supply them with a PATCH, then submit again.pending: the review is running. Wait forendorsement.approved.issues: see Verification needs more information.
3. 400 verification_required
The customer's own verification is not approved. Submit them if you have not:
curl -s $BASE/api/customers/cus_.../verifications/submit \
-H "Api-Key: $KEY" -H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" -d '{}'
422 verification_incomplete from that call names exactly which inputs are
still outstanding.
4. 400 customer_name_required
The customer has no name on file, and the name becomes the account holder
name on the account. Names are optional at creation, and usually backfilled
from the verified identity, but a nameless customer cannot reach the
banking rail. PATCH in first_name and last_name, or legal_name for a
business.
Other refusals
| Code | Meaning | Fix |
|---|---|---|
unsupported_corridor | That currency and destination pair is not enabled for you | Check GET /api/corridors |
unsupported_rail | The rail does not serve the currency | Use ach or wire with usd |
unsupported_chain | The destination chain is not enabled | Solana is live today. See Coverage |
virtual_account_exists | This customer already has that rail and currency | PATCH the existing account's destination instead of creating a second |
partner_reference_id_exists | Your reference id is already used in this environment | Use a different one |
Checking before you call
A customer's readiness is entirely visible before you attempt creation:
curl -s $BASE/api/customers/cus_... -H "Api-Key: $KEY"
Look at endorsements. If the endo_usd entry reads approved with empty
missing and issues buckets, and the customer has a name, creation will
succeed.