| Model | Key custody | Built for |
|---|---|---|
| Custodial | OMS holds the keys | Regulated fintech, neobanks, and remittance products |
| Non-custodial | The user holds the keys | Consumer apps where users control their own funds |
| Agentic | The agent holds scoped keys | Autonomous agents with policy-based spending limits |
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.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.bankDetails to display in your UI (null 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 fiatAccountToCrypto transaction directly in processing.
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} returns 202 and initiates closure of the underlying deposit account, and the status finalizes to deleted once it closes. A sandbox POST /virtual-accounts/{id}/simulate endpoint exercises the inbound flow. See Virtual accounts.
Deposit addresses
A reusable on-chain address wired to a fiat destination. On-chain deposits auto-create a transaction.cryptoToFiatAccount transaction directly in processing.
Deposit addresses are managed through the API: create with POST /deposit-addresses (the destination is a registered bank external account), list with GET /deposit-addresses, read and update with GET/PATCH /deposit-addresses/{id}. There is no delete. depositInstructions is null until provisioning populates the OMS-owned inlet address, and 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. A sandbox POST /deposit-addresses/{id}/simulate endpoint exercises the inbound flow. 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. Each external account is referenced by an ID whose prefix identifies the account type:| Prefix | Type |
|---|---|
ext_card_ | Debit card |
ext_bankUs_ | US bank account (ACH, same-day ACH, wire, RTP) |
ext_bankIban_ | IBAN bank account (international, SWIFT) |
ext_bankCa_ | Canadian bank account |
ext_wlt_ | External wallet |
POST /external-accounts. The body specifies an owner (a customer, or one of the customer’s counterparties), a type (bankUs, bankIban, bankCanada, card, or walletExternal), and exactly one per-type details object matching the type; debit cards register through this same endpoint. List with GET /external-accounts (requires customerId, with an optional counterpartyId filter), update label and metadata with PATCH, and remove with DELETE. When delivering to a raw on-chain wallet, a quote can also pass a blockchainAddress directly instead of an ext_wlt_ 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.