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 quote’s sourceToDestination field is a composite of the source and destination instrument categories, inferred from each side. Filter GET /transactions by the same values:
Two-step flow
POST /transactions with a body of { "quoteId": "qt_..." }. If the quote expires before you create the transaction, create a new quote.
Quote object
pricing.fixedAmountSide to "source" when the user specifies how much to send, or "destination" when the user specifies how much to receive.
Pricing
Every quote, transaction, and cash-in renders pricing in one shape:
Every amount is a decimal string padded to the asset’s own precision: six decimals for
usdc/usdt, two for usd/eur, three for bhd, eighteen for eth. The same amount renders the same string on every network and in every response and webhook. Do not trim or re-round the value; display it as received or format it with your locale.
Instrument shape
Thesource and destination are typed instruments discriminated by type. There are ten arms: walletCrypto, walletFiat, walletExternal, bankUs, bankIban, bankCanada, card, cash, and the auto-created-flow arms depositAddress and virtualAccount. Each instrument carries type, asset, and, where applicable, id, network, owner, and details:
Owner, precursor, and payout origin
Transaction responses carry three flat reference objects that identify who owns a non-customer account, what created the transaction, and whose name the payout goes out under:
Dereference the referenced resource by
id to retrieve richer detail. Bank account numbers, routing numbers, and BICs are not returned on payoutOrigin; read them from the funding virtual account or external account directly. payoutOrigin is left out when nothing is paid out to a bank account, a card, or a wallet, so cash payouts and fiat-wallet credits carry none; a cash payout carries its pickupCode on the cash destination instead.
The same payoutOrigin is carried at the top level of the transaction, the deposit address, and the virtual account.
Rendering an instrument
The typeddetails object on each instrument carries the fields you need to label the side in your UI. Instruments carry no pre-formatted display string, so you choose the label that fits your layout. Common recipes:
A counterparty-owned bank account also carries
owner.name with the counterparty’s name. details.holderName carries the account holder: the counterparty’s name, or the sender’s name when the rail carries it. A customer’s own name lives on the customer resource.
Bank memo
Bank source and destination instruments carry an optionalmemo field inside details on transaction responses. When populated, it echoes the wire, ACH, or SWIFT memo that actually travelled on the rail:
SELL PROCEEDS line) never appears in the response. The field is present on GET /transactions/{transactionId}, on every entry of GET /transactions, and on transaction.statusChanged webhook payloads. Non-bank arms do not carry a memo.
Transfers and rail tracking
A transaction’stransfers array lists each movement of its money on one rail, in creation order. Each entry names the transfer id (trf_ prefix), its role, its rail, and its attempt:
GET /transfers/{transferId} to read the rail references in its tracking object:
tracking is left out until OMS holds a reference. The transfer also carries its own status, amount, from and to instruments, and, for an ACH payout, the secCode and companyDiscretionaryData it was sent with. See Transfers for roles, attempts, and transfer statuses.
Customer reference
Every transaction, quote, deposit address, virtual account, cash-in, external account, and customer wallet carries acustomer reference that identifies the owning customer in one hop:
GET, list, and POST/PATCH response, and on every v1 webhook payload. Dereference the customer by id to read their name, status, and endorsements; names are not denormalized onto the parent resources. This resolves the customer in one shape across every resource that references one.
Transaction statuses
OMS fires
transaction.statusChanged on every status change, so your handler branches on the transaction’s status field rather than parsing an event-name string. Subscribe with the Webhooks endpoints (POST /webhooks with a body of { url, subscriptions }; pass ["*"] for all partner-visible 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 as entries in thepricing.fees array with type: "developer", carrying the amount, asset, and side of the fee.
Timestamps
Every date-time rendered on these resources (and on their v1 webhook payloads) is UTC with three-digit millisecond precision, for example2026-10-16T10:35:00.123Z. Parse the value with any ISO 8601 parser; do not depend on a fixed character count.
Key operations
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.Related
- Fiat to crypto guide: cash-in and virtual-account funding
- Send from a wallet guide: crypto sends and bank payouts
- Bank transfers guide: ACH and wire transfer details