Skip to main content
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 on the quote 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 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

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

Set 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

The source 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 typed details 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 optional memo field inside details on transaction responses. When populated, it echoes the wire, ACH, or SWIFT memo that actually travelled on the rail:
OMS echoes only memos that a sender supplied. Any default text OMS may compose on behalf of a rail (for example, a 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’s transfers 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:
The array is left out until the first transfer exists. Fetch a transfer with 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 a customer reference that identifies the owning customer in one hop:
The field is populated on every 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 the pricing.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 example 2026-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.