Skip to main content

Goal

Withdraw USDC from a customer’s Bastion account to their own US bank account in USD, using an off-ramp conversion. Scope: USDC to USD, wire only, first-party only (the customer withdraws to a bank account they own). To pay out to a bank account outside the United States, or to a third party, see Withdraw stablecoin to an international bank account.

Key entities

Flow overview

The steps to withdraw funds from a stablecoin balance to a US bank account are:
  1. Confirm identity, account, and balance
  2. Register payment instructions
  3. Submit the conversion
  4. Track status
  5. Show updated balance

Prerequisites

  • Customer has a verified identity (KYC or KYB) with fiat_operations_enabled = true
  • Customer has an on-chain account with a USDC balance on a supported chain
  • You have an API key and a registered webhook
  • The customer’s principal address is not in New York. See Jurisdiction overview
US off-ramps are supported on Ethereum, Solana, and Base. See Supported chains and assets.

Step 1 – Confirm identity, account, and balance

Before allowing a withdrawal, confirm the customer can transact and has sufficient balance. Get the identity
Verify these fields: Get balances
Balances are returned in base units. Divide by 10 ^ decimals to get the decimal amount: 750000000 with decimals: 6 is 750.000000 USDC. Conversions take decimal strings, not base units. Verify available covers the withdrawal amount. Fees are deducted from that amount rather than added to it, so the customer’s total debit equals the amount you submit.

Step 2 – Register payment instructions

Register the customer’s bank account as payment instructions. The returned payment_instructions_id is reusable across withdrawals to the same bank account. Request
Field notes Response
Store the id as payment_instructions_id so you can reference it on the conversion request and reuse it for future withdrawals to this bank account.

Step 3 – Submit the conversion

Submit a conversion that debits USDC from the customer’s account and sends USD to their bank. Request
payment_purpose is required and must describe the nature of the payout. See the API reference for valid values. destination.payment_method and destination.currency must match the payment_method and fiat_currency_symbol on the registered payment instructions. Response - INITIATED
The PLATFORM fee is the wire processing cost. It is deducted from amount before payout, so destination.amount is amount minus fees_total.
Tip: use a unique request_id (UUID) as an idempotency key, and reuse the same request_id on retries. The payment_instructions_id can be reused across withdrawals to the same bank account.

Step 4 – Track conversion status

Track the conversion via webhooks (recommended) or polling until it reaches a terminal state.

Option A: Webhooks

Configure a webhook endpoint in the Bastion dashboard to receive conversion events. Each event carries the conversion object in data, using the same shape as the submit response.
The top-level id is unique per delivery. The stable conversion ID is data.id. See Conversion notifications for the full schema. On FAILED and RETURNED, the event carries failure_reason with a human-readable description of what went wrong. Log it, and use it to decide between prompting the customer to correct bank details and routing to support. Do not display it to the customer verbatim. Status progression INITIATED to PROCESSING to PAYOUT_INITIATED to PAYOUT_IN_PROGRESS to COMPLETED Handle statuses: For canonical status definitions and recovery guidance, see Stablecoin and fiat conversions.
Webhook reliability: failed deliveries are retried with exponential backoff (15 s base interval, 10 min max). Deduplicate using data.id and data.status. If no webhook arrives within a reasonable window, poll GET /v2/conversions/{conversion_id}.

Option B: Polling

Poll GET /v2/conversions/{conversion_id} as a fallback. Use the returned status and fee breakdown to update your UI.

Step 5 – Show updated balance

After the conversion completes, refresh balances and show the withdrawal in your history.
UI recommendations:
  • Decrease the visible USDC balance by the amount submitted, which includes fees
  • Display the amount, the asset (USDC), the USD delivered, and the status
  • Show the destination with masked bank account details

Implementation notes

What’s next