A transaction moves money through OMS. You specify a source instrument and a destination instrument on the quote; OMS infers the direction from those two sides and reports it as sourceToDestination. There is no settable transaction “type”.
Standard sends and payouts follow a two-step flow: create a quote to lock pricing, then create a transaction to execute it. Cash-in and auto-created transactions (virtual accounts, deposit addresses) skip the quote step.
Direction (sourceToDestination)
The sourceToDestination field is a composite of the source and destination instrument categories, inferred from each side:
| Value | Source | Destination |
|---|
cryptoToCrypto | OMS wallet | OMS wallet or external on-chain address |
cryptoToFiatAccount | OMS wallet | Registered bank external account |
cryptoToCash | OMS wallet | Cash pickup (early access) |
fiatAccountToCrypto | Bank account, via a virtual account | OMS wallet |
cashToCrypto | Cash, via a cash-in | OMS wallet |
Two-step flow
POST /quotes → quote in "open" status (rate locked)
│
POST /transactions → transaction in "processing"
│
completed | failed
The quote locks the exchange rate and fee breakdown for a short validity window. To execute it, call POST /transactions with a body of { "quoteId": "qt_..." }. If the quote expires before you create the transaction, create a new quote.
Quote object
{
"id": "qt_...",
"object": "quote",
"status": "open",
"customerId": "cst_...",
"sourceToDestination": "cryptoToCrypto",
"source": {
"type": "walletOms",
"category": "crypto",
"details": {
"id": "wlt_...",
"asset": "usdc",
"network": "polygon"
}
},
"destination": {
"type": "walletExternal",
"category": "crypto",
"details": {
"blockchainAddress": "0x...",
"asset": "usdc",
"network": "polygon"
}
},
"pricing": {
"source": {
"asset": "usdc",
"amountGross": "100.00",
"amountNet": "99.42",
"feesDeducted": { "total": "0.58", "developer": "0.20", "oms": "0.35", "gas": "0.03" }
},
"destination": {
"asset": "usdc",
"amountGross": "99.42",
"amountNet": "99.42"
},
"pair": "usdc/usdc",
"exchangeRate": "1.0",
"effectiveRate": "0.9942",
"fixedAmountSide": "source"
},
"expiresAt": "2025-01-15T10:35:00Z"
}
Set pricing.fixedAmountSide to "source" when the user specifies how much to send, or "destination" when the user specifies how much to receive.
The source and destination are typed instruments discriminated by type: an OMS wallet (walletOms), an externally-custodied wallet (walletExternal), a bank account (bankUs, bankIban, bankCanada), a debit card (card), or cash pickup (cash).
Transaction statuses
| Status | Meaning |
|---|
processing | Executing. Funds are being pulled or converted. |
awaitingAction | Non-terminal. Blocked on developer, upstream, or compliance action; see the hold object. Returns to processing once cleared. |
completed | Funds delivered to the destination. |
failed | Terminal failure. The error object describes the cause. |
OMS fires a webhook on every status change. Each delivery carries the full transaction object, so your handler branches on the status field rather than parsing an event-name string. Subscribe with the Webhooks endpoints (POST /webhooks with a body of { url, events }; omit events or pass ["*"] for all events) or in the OMS Dashboard. See the transaction lifecycle for the delivery model.
Developer fees
Developer fees are configurable per integration and are never shown to the end user. Set them on your OMS account or pass them in the quote request. They appear in the feesDeducted.developer field on both the source and destination sides of the pricing object.
Key operations
| Operation | Endpoint |
|---|
| Create a quote | POST /quotes |
| Get a quote | GET /quotes/{quoteId} |
| Create a transaction | POST /transactions |
| Get a transaction | GET /transactions/{transactionId} |
| List transactions | GET /transactions |
GET /transactions returns results newest-first and filters by status, sourceToDestination, customerId, the originating instrument (walletId, virtualAccountId, depositAddressId, cashInId), and inclusive createdAfter/createdBefore date bounds. Pagination uses limit, startingAfter, and endingBefore.
All POST endpoints accept an Idempotency-Key header. Use a stable key tied to your internal order ID to safely retry on network failure without risk of double-execution.