Skip to main content
Trade Settlement surfaces the three things you do with funds: receive (deposits), see (balances), send (withdrawals). Fiat and stablecoin share a single withdrawal endpoint; the rail is inferred from the verified withdrawal account.

Fiat

The withdrawal account is a bank account on a rail (wire, SEPA, ACH, FPS, SPEI). Settlement is T+0 or T+1 depending on the rail and the submission cut-off. Rail is bound to the verified withdrawal account; you don’t pick it on the request.

Stablecoin

The withdrawal account is a wallet on a blockchain (EVM chains, Solana). Settlement is typically minutes, gated by on-chain confirmations. The chain is bound to the verified withdrawal account and reported on network.
One POST /v3/fx/withdrawals shape covers both fiat and stablecoin because the asset family is inferred from withdrawalAccountId. Your client code branches on the verified withdrawal account, not on the endpoint — you write one withdrawal path and let OpenFX route it.

The fund-movement flow

Endpoints

The verified-account model

Every withdrawal references a withdrawalAccountId, a verified withdrawal account configured ahead of time. The withdrawal account can be:
  • A fiat bank account on a specific rail. See Settlement times for per-rail submission cut-offs by currency.
  • A stablecoin wallet on a specific blockchain. See Supported networks for the per-stablecoin chain matrix.
You don’t need to declare the type or rail when withdrawing; OpenFX infers both from the verified withdrawal account. This means one endpoint (POST /v3/fx/withdrawals) covers both fiat and stablecoin with the same request shape.
v2 had two account surfaces and two withdrawal endpoints; v3 collapses them into one. GET /v2/brokerage/{orgId} /withdrawal_addresses (stablecoin wallets) and GET /v2/brokerage/{orgId} /fiat_withdrawal_addresses (fiat bank accounts) both fold into GET /v3/fx/withdrawal-accounts. Likewise, POST /v2/.../withdrawal and POST /v2/.../fiat_withdrawal become a single POST /v3/fx/withdrawals.
Verified accounts are dashboard-managed. Add accounts via the OpenFX dashboard; your integration reads them via GET /v3/fx/withdrawal-accounts.
One account record = one address × one network × one asset. If you want to withdraw USDC and USDT to the same Ethereum address, you add two verified accounts via the dashboard — one per (address, network, asset) combination. Likewise, the same address on Ethereum mainnet vs Polygon is two separate accounts. This is intentional: it protects clients who fund from exchanges (where the same nominal address may not actually be controlled across all chains, and tokens may have distinct deposit addresses even on the same chain) from accidentally configuring an unreachable destination. If you control all your custody and the same address works for every chain × asset combination, you still add each tuple explicitly — there is no bulk-add.
Each verified withdrawal account carries a displayName — the customer-set label captured at verification (for example "Acme Corp checking" for fiat, "Treasury wallet" for stablecoin) — that’s safe to render directly in your UI.
Do not parse displayName. The format is not guaranteed. Render it as-is for human display; use the structured fields (type, currency, network, address) for any logic, filtering, or routing.

Balances

Balances are returned per currency, with two amounts:
  • availableBalance: usable for new trades or withdrawals right now
  • totalBalance: total held in the currency, including any amount earmarked against pending operations (availableBalancetotalBalance)
Some funds may be held against pending operations, so availableBalance can be lower than totalBalance. The held portion is the difference totalBalance − availableBalance; it is not broken out as a separate field in v3 (a richer breakdown may be added later). After a trade, the bought currency’s availableBalance rises. After a withdrawal completes, the held funds leave the balance entirely and totalBalance drops to match availableBalance. See Amounts for the string-encoding rules.

Resource lifecycles

Both deposits and withdrawals have multi-step lifecycles. Track them with the dedicated pages:

Withdrawal lifecycle

State machine + polling pattern.

Deposit lifecycle

How deposits are detected + completed.

Common errors

For status codes and machine-readable error codes returned by these endpoints, see the Withdrawal catalog in Errors. One withdrawal-specific recovery rule to know:
  • WITHDRAWAL_PENDING_DEPOSIT_REQUIRED: an outstanding settlement deposit must clear before any new withdrawal goes out. Resolve the upstream deposit, then retry as a new operation with a NEW idempotency key.

What’s next

Trade

Quote and execute FX trades — the other half of the product.

Verified accounts

Register the destinations you’ll withdraw to before going live.

Webhooks setup

Receive deposit and withdrawal events without polling.

Idempotency

7-day TTL on withdrawal keys (carried forward from v2); crash-safe retry pattern.