The entity model
Customer. A customer has zero or more wallets. Counterparties, virtual accounts, deposit addresses, quotes, and transactions are also scoped to a customer; external accounts belong to a customer or to one of its counterparties. Webhook subscriptions are managed through the API independently of any customer.
Customers
A customer is an identity record. Before a customer can move money, OMS must grant endorsements that unlock specific capabilities.| Endorsement | Unlocks |
|---|---|
basic | Standard operations |
cryptoCustody | Crypto custody and advanced features |
usd | USD stablecoin operations |
POST /customers with a type (for example individual) and an endorsements array. Endorsements are granted after KYC/KYB verification; a webhook fires as they change.
Wallets
The Payments APIwallet resource is custodial: OMS manages the keys, and they never leave OMS infrastructure. Wallets hold stablecoin balances (USDC by default) and are the source or destination for all transactions.
Wallets are created and listed under the customer: POST /customers/{id}/wallets (body specifies asset and chain) and GET /customers/{id}/wallets. Each wallet holds a single asset on one chain and has an onchain address. GET /wallets/{id}/balance returns that wallet’s current balance for its asset and chain.
For user-controlled keys (onchain consumer apps, agentic flows), use OMS non-custodial wallets. The two models can be combined.
Virtual accounts
A dedicated bank account number assigned to a customer. When fiat arrives via a supported bank rail, OMS automatically creates afiatAccountToCrypto transaction and delivers USDC to the customer’s wallet.
Create one with POST /virtual-accounts; the body specifies the customerId, the source asset and network, a destination (an OMS wallet, or a registered external wallet by ID), the accountHolder (always customer), and the account type (bankUs). The response’s bankDetails is null until the underlying deposit account is provisioned. Virtual accounts support list, get, and update (GET /virtual-accounts, GET/PATCH /virtual-accounts/{id}). Deletion is asynchronous: DELETE /virtual-accounts/{id} returns 202, and the status finalizes to deleted once the underlying account closes.
Deposit addresses
A persistent onchain address. When crypto arrives, OMS automatically creates and executes a transaction that delivers fiat to a registered bank external account. Create one withPOST /deposit-addresses; the body specifies the customerId, the expected source asset (usdc or usdt) and network, and a registered bank external account as the destination. The response’s depositInstructions is null until provisioning populates the OMS-owned inlet address. Deposit addresses support list, get, and update (GET /deposit-addresses, GET/PATCH /deposit-addresses/{id}); there is no delete. Deposit addresses must be enabled for your project: contact us to enable them.
Counterparties
A person or business a customer transacts with, scoped to that customer. Create one withPOST /counterparties; the body requires customerId and name, with optional identity fields (entityType, email, phone, dateOfBirth, taxId, nationality, address, metadata). The address object takes streetAddress, city, postalCode, and country, plus an optional countryArea.
Counterparties support full CRUD. Listing requires the customerId query parameter (GET /counterparties?customerId=...). A counterparty can own external accounts; DELETE /counterparties/{id} returns 409 while the counterparty still owns active external accounts.
External accounts
A registered bank account, debit card, or external wallet, owned by a customer or by one of the customer’s counterparties. External accounts are referenced by ID as the source for on-ramps or the destination for off-ramps. Register one withPOST /external-accounts. The body specifies the owner ({ kind: "customer", customerId } or { kind: "counterparty", counterpartyId }), 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. GET /external-accounts requires a customerId and accepts an optional counterpartyId filter; PATCH updates label and metadata; DELETE removes the registration.
ID prefixes: ext_card_ (debit cards), ext_bankUs_ (US banks), ext_bankIban_ (IBAN banks), ext_bankCa_ (Canadian banks), ext_wlt_ (external wallets).
Quotes and transactions
The two-step flow for most money movement:POST /quotes: lock pricing, return full fee breakdownPOST /transactions: execute against the locked quote
pricing.fixedAmountSide indicates which side of the trade was specified.
Cash-ins
A code-based deposit flow for in-person cash at retail locations. Creates a deposit code the customer presents at a partner location. OMS converts the deposited cash to USDC and auto-creates a transaction. No upfront amount is required.Webhooks
API-managed event subscriptions with full CRUD. Register a subscription withPOST /webhooks (body { url, events }) and OMS delivers events as state changes occur; each delivery carries the full object so your handler branches on its status. Subscribe to specific event types, or pass an empty events array (or ["*"]) to receive all of them. Subscriptions are created, listed, updated, and deleted through the API (GET/PATCH/DELETE /webhooks/{id}) as well as in the dashboard. The create response returns a signing secret once for verifying the Webhook-Signature header.
Virtual accounts, deposit addresses, and cash-ins all bypass the quote step. They go directly to
processing because OMS cannot lock pricing before the funds arrive.