Goal
Fund a customer’s Bastion account with USDC by converting USD wired from their bank account, using an on-ramp conversion via a Virtual Account (VA).Scope: USD → USDC, Wire only, US customers only, first-party (customer wires from their own bank account).
Key entities
Flow overview
The steps to fund a stablecoin balance from a bank account are:- Create a Virtual Account
- Share deposit instructions with the customer
- Customer wires USD
- Track conversion status
- Show balance
POST /v2/conversions. The conversion is auto-created the moment Bastion detects the incoming wire.
Prerequisites
- Customer has a verified identity (KYC or KYB) with
fiat_operations_enabled = true - Customer has an active Bastion account on a supported chain
- You have an API key and registered webhook
Step 1 – create a virtual account
Create a Virtual Account for the customer. Each VA links to a specific chain, asset, and destination wallet; create one VA per chain and asset you want to support. Request
Response
id as virtual_account_id so you can reference this VA later. You can retrieve it again at any time from the GET /v2/identities/{identity_id}/virtual-accounts list endpoint.
Step 2 – share deposit instructions with the customer
Present thedeposit_instructions from Step 1 to the customer so they can initiate a wire from their bank.
Fields to surface in your UI
The
bank_account_number is unique to this VA. The customer does not need to include a memo or reference — the account number alone routes the deposit to the correct VA.
Step 3 – customer wires USD
The customer initiates a domestic wire from their bank to the deposit instructions shared in Step 2. When the wire lands at Bastion’s banking partner, Bastion detects it and auto-creates a conversion record. No API call is required from your platform at this step.Step 4 – track conversion status
Once the wire is detected, Bastion creates the conversion and fires webhooks as it progresses. You learn theconversion_id from the first webhook.
Option A: webhooks
Example event (INITIATED)INITIATED → PROCESSING → PAYOUT_INITIATED → PAYOUT_IN_PROGRESS → COMPLETED
Handle statuses:
Webhook reliability: Failed deliveries are retried with exponential backoff (15 s base interval, 10 min max). Deduplicate usingid+status. If no webhook arrives within a reasonable window, pollGET /v2/conversions/{conversion_id}.
Option B: polling
If webhook delivery fails, list conversions by account to find the record:GET /v2/conversions/{conversion_id} for status updates.
Step 5 – show updated balance
After the conversion completes, refresh balances and show the on-ramp in the customer’s history. Refresh balances- Increase visible USDC balance by
destination.amountfrom the completion webhook - Display USD wired (gross), fees, USDC delivered (net), and status
- Show source (masked bank account details from the wire)
Fees
fees_total on the conversion reflects the incoming wire fee only. The fee is deducted from the wired USD amount before USDC is delivered.
Example: customer wires $500 → fees_total = 14.00 → destination.amount = 486.00 USDC delivered.
The fees array is populated from the moment the conversion is created (when the wire lands).
Developer fees are not supported yet.