Skip to main content
OMS supports flexible custody models. Pick the model that fits your product; the rest of the OMS API (transactions, quotes, compliance, on-ramps and off-ramps) works the same across all three. A single product can combine them: custodial for fiat flows and compliance, non-custodial for user-controlled on-chain assets, agentic for autonomous payments. The remainder of this page covers the account types used by the custodial model. For non-custodial and agentic wallets, see OMS wallets.

Custodial wallets

The primary balance store. OMS manages private keys, with no end-user signing and no wallet SDKs required. All operations are server-to-server API calls.
Each custodial wallet holds a single asset on one chain and has an on-chain address. The type field is internal for OMS-managed wallets. blockchainAsset resolves the on-chain identity of the asset (protocol, chain ID, and token ID). Creating a wallet: POST /customers/{customerId}/wallets with asset and chain. Returns the created wallet record. Listing wallets: GET /customers/{customerId}/wallets returns the customer’s wallets, one per asset and chain. Reading a balance: GET /wallets/{walletId}/balance returns the wallet’s current balance for its asset and chain, along with an estimated value in the requested currency. Funding a wallet: Send crypto directly to the wallet’s address, or use the on-ramp flows (cash-in, virtual accounts, deposit addresses) to convert fiat. Multiple wallets: A customer can have more than one wallet, for different currencies, use cases, or segregation needs.
At launch, OMS custodial wallets are internal (OMS-managed). Embedded wallets, provisioned through the same customer endpoint, are planned for a later release.

Virtual accounts

A bank account number wired to a customer’s wallet. Fiat deposits auto-convert to crypto.
Give your customers the depositInstructions to display in your UI (left out until the underlying deposit account is provisioned). A transfer to that account number delivers crypto to the configured wallet. When funds arrive, OMS creates a transaction directly in processing: fiatAccountToCrypto for a crypto wallet destination, or fiatAccountToFiatAccount for a bank or fiat wallet destination. Virtual accounts are managed through the API: create with POST /virtual-accounts, list with GET /virtual-accounts, read and update with GET/PATCH /virtual-accounts/{id}. Deletion is asynchronous: DELETE /virtual-accounts/{id} initiates closure of the underlying deposit account; the status reads deleting until it closes, then finalizes to deleted. A sandbox POST /virtual-accounts/{id}/simulate/inbound-transfer endpoint exercises the inbound flow. See Virtual accounts.

Deposit addresses

A reusable onchain address wired to a destination. Onchain deposits auto-create a transaction.
Deposit addresses carry routing configuration, so any deposit to the inlet address is delivered to the configured destination. They are the pattern for “accept any amount from any sender” flows. When funds arrive, OMS creates a transaction directly in processing: cryptoToFiatAccount for a bank or fiat wallet destination, or cryptoToCrypto for a registered external wallet. Deposit addresses are managed through the API: create with POST /deposit-addresses (the destination is a registered bank external account, the customer’s fiat wallet, or a registered external wallet), list with GET /deposit-addresses, read and update with GET/PATCH /deposit-addresses/{id}. There is no delete. depositInstructions carries the accepted asset and network from creation, and its address is left out until the inlet address is issued. Re-pointing the destination to a healthy external account recovers an inactiveActionRequired address to active. Deposit addresses must be enabled for your project: contact us to enable them. See Deposit addresses.

External accounts

Off-platform bank accounts, external wallets, and debit cards, referenced on a quote by their ID. A quote’s source is always an OMS wallet or a card, so banks are destinations. Every external account ID uses the same ext_ prefix, whatever the instrument. The type field on the resource identifies the instrument: Register bank accounts and external wallets with POST /external-accounts. The body specifies an owner (a customer, or one of the customer’s counterparties), a type (bankUs, bankIban, bankCanada, or walletExternal), and exactly one per-type details object matching the type. Debit cards register through their own endpoint, POST /external-accounts/cards; the generic endpoint rejects type: card with CardMustUseCardEndpoint. See Debit cards. List with GET /external-accounts (optional customerId, counterpartyId, and status filters), update label and metadata with PATCH, and remove with DELETE. When delivering to a raw onchain wallet, a quote can also pass a blockchainAddress directly instead of a registered external wallet’s ext_ ID.
External accounts are not OMS-managed balances. OMS never holds funds in an external account; it is only a source or destination reference on a transaction.

Forward-looking

Embedded custodial wallets, provisioned alongside the internal wallets available today, are planned for an upcoming release.