Virtual Accounts & Deposit Addresses
The two ways money reaches a customer.
A virtual account receives fiat and a deposit address receives stablecoin. Both belong to a customer, and neither holds a balance.
Virtual accounts
POST /v1/customers/{customerId}/virtual_accounts
{
"purpose": "PAYMENT",
"currency": "USD",
"label": "supplier-settlement"
}The instrument is issued to the customer, and every deposit that lands on it is attributed to that customer. It comes back with instructions, which is what you give a payer.
Render whatever instructions contains rather than picking fields by name. What a payer needs differs per market. A US account carries routing and account numbers, and a local one carries the identifier that market uses. A screen that renders the fields it is given works in every market without a change, so adding a market is a configuration change rather than a release.
instructions.beneficiary_name is an attribution name, not a statement of legal title. It carries the customer's legal name, which is what lets a payer and a bank tie the payment to that customer. Who legally holds the underlying account is a separate question, and the answer depends on the market and on how Alfred is licensed there. In some corridors the two are the same party and in others they are not. Confirm it per corridor before you print a beneficiary name on an invoice or a payment instruction.
In Mexico, the account is held by FastCash S.A. de C.V., Alfred's money transmitter there. The CLABE sits on FastCash's account at STP, so FastCash is the name a payer's bank shows as the account holder. Tell payers to enter your customer's name as the beneficiary.
Two conditions have to be true first. The customer must hold the endorsement that the chosen purpose needs. The purpose must also be among the accountPurposes they declared during onboarding. A purpose they never declared counts as a material change, so update the profile and have it re-evaluated before you create the instrument.
Wait on virtual_account.activated before giving anyone the deposit instructions.
Purpose is permanent
purpose decides what happens to every deposit that ever lands on this instrument, and it is fixed at generation. There is no PATCH for it. If you need a different purpose, create a separate instrument.
| Purpose | A deposit here | Needs |
|---|---|---|
CONVERSION | Enters the conversion flow, into USDC or USDT | fiat_collection + stablecoin_balance |
BALANCE | Issues a local stablecoin: MXNa, ARSa, COPa or BRZ | The endorsement for that specific asset, in a country where it exists |
PAYMENT | Is matched to a locked order. It is never converted or issued automatically | fiat_payout.cross_border |
The three purposes are mutually exclusive. The value selects which downstream flow a deposit enters.
The rule exists to stop a deposit arriving on a CONVERSION account from silently creating a stored balance that the customer isn't approved to hold.
Two similar names
These two fields are easy to confuse.
accountPurposeson the customer is plural and declared at onboarding. It controls which purposes you may create instruments for, and it does not route anything.purposeon the instrument is singular and immutable. It routes everything that lands there.
Labels and idempotency
Idempotency is scoped to (customerId, label). Repeating a label returns the account you already have. Repeating it with a different purpose is a 409.
Choose labels deliberately, because they are how you tell your own instruments apart and how you avoid creating a second one by accident.
Reading them back
GET /v1/customers/{customerId}/virtual_accounts
GET /v1/virtual_accounts/{virtualAccountId}
GET /v1/virtual_accounts/{virtualAccountId}/deposits
More than one instrument per customer is normal.
A virtual account never holds a balance, so the deposit list is the closest thing it has to one. It shows the flow through the instrument. The balance itself lives on the customer.
Deposit addresses
GET /v1/customers/{customerId}/deposit_address?chain=SOL
This retrieves an existing address rather than creating one.
The custody provider supplies the address and attributes it to the customer when it is issued. The address is permanent, and you do not register, rotate or mint it. Use chain to pick which address you get back when more than one chain is enabled.
Arrivals show up as ordinary deposits. Third-party senders are supported and screened.
What comes next
Money arriving on either instrument is a deposit. Whether you announce it in advance changes what happens, and the pay-in flow under Step by Step covers that.
Updated 3 days ago

