Skip to main content
OMS delivers webhooks for every meaningful state change. Subscribe with POST /webhooks, passing a url and the events you want; omit the list or pass ["*"] to receive everything. Verify every delivery with the Webhook-Signature header before processing, and use the envelope’s eventId to handle retries idempotently. This page lists every event you can receive and the envelope it arrives in.

Event envelope

Every event shares one envelope. The resource that changed is carried in full under payload, so you rarely need a follow-up read.
FieldTypeDescription
eventIdstringUnique, stable ID for this event. Use it to deduplicate retried deliveries.
eventNamestringThe event type from the catalog below.
schemaVersionintegerEnvelope schema version.
producerServicestringThe OMS service that produced the event.
orgIdstringYour organization.
projectIdstringThe project the event belongs to. Optional.
customerIdstringThe customer the resource belongs to, when applicable. Optional.
modestringThe environment the event was produced in. Optional.
resourceTypestringThe kind of resource in payload (for example cashIn, virtualAccount, transaction_crypto_to_fiat).
resourceIdstringThe ID of the resource in payload.
sequenceintegerMonotonic sequence for ordering events about the same resource. Optional.
occurredAttimestampWhen the event occurred.
correlationIdstringCorrelates events produced by the same logical operation. Optional.
causationIdstringThe event that caused this one, when applicable. Optional.
payloadobjectThe full resource object at the time of the event.
{
  "eventId": "evt_01H9Xz4M2k7vP3qR8t",
  "eventName": "transaction.cryptoToFiat.completed",
  "schemaVersion": 1,
  "producerService": "api",
  "orgId": "org_01H9Xo...",
  "projectId": "prj_01H9Xp...",
  "customerId": "cst_01H9Xa...",
  "mode": "production",
  "resourceType": "transaction_crypto_to_fiat",
  "resourceId": "txn_01H9Xd...",
  "sequence": 42,
  "occurredAt": "2026-07-08T12:00:00Z",
  "payload": { "id": "txn_01H9Xd...", "object": "transaction", "status": "completed", "...": "..." }
}
The resource’s status lives inside payload, not on the envelope: branch on payload.status (or the event name itself) rather than expecting envelope-level status fields.

Transactions

Transaction events are namespaced by transfer type. Refund events fire when a failed transaction’s funds are returned (see Returns and refunds).
EventFires when
transaction.fiatToCrypto.processingA fiat-funded transaction starts executing.
transaction.fiatToCrypto.completedCrypto delivered to the destination.
transaction.fiatToCrypto.failedThe transaction failed; see payload.error.
transaction.fiatToCrypto.refundCompletedThe refund for a failed transaction was delivered.
transaction.fiatToCrypto.refundFailedThe refund itself failed; operator follow-up.
transaction.cryptoToFiat.processingA crypto-funded payout starts executing.
transaction.cryptoToFiat.cashPickupReadyCash payout only: the pickup code was issued.
transaction.cryptoToFiat.codeExpiredCash payout only: the pickup code expired uncollected.
transaction.cryptoToFiat.completedFiat delivered to the destination.
transaction.cryptoToFiat.failedThe payout failed; see payload.error.
transaction.cryptoToFiat.refundCompletedThe stablecoin re-credit for a failed payout was delivered.
transaction.cryptoToFiat.refundFailedThe re-credit itself failed; operator follow-up.
transaction.cryptoToCrypto.processingA crypto-to-crypto send starts executing.
transaction.cryptoToCrypto.completedCrypto delivered to the destination.
transaction.cryptoToCrypto.failedThe send failed; see payload.error.
transaction.cryptoToCrypto.refundCompletedThe refund for a failed send was delivered.
transaction.cryptoToCrypto.refundFailedThe refund itself failed; operator follow-up.

Cash-in

EventFires when
cashIn.createdA cash-in code was issued.
cashIn.completedThe cash was deposited and converted; the auto-created transaction is linked on the cash-in.
cashIn.expiredThe code expired before a deposit was made.

Virtual accounts

EventFires when
virtualAccount.createdThe virtual account record was created.
virtualAccount.provisionedThe underlying deposit account was provisioned; bankDetails is populated.
virtualAccount.activeThe account is live and accepting deposits.
virtualAccount.frozenDeposits are suspended.
virtualAccount.closedThe account reached end of life.
virtualAccount.deletedAn asynchronous delete finalized.
virtualAccount.failedProvisioning failed.
virtualAccount.deposit.pendingAn inbound bank deposit was detected and is settling.
virtualAccount.deposit.settledThe inbound deposit settled.
virtualAccount.deposit.failedThe inbound deposit failed.
virtualAccount.deposit.returnedThe inbound deposit was returned by the bank.
virtualAccount.cryptoTransfer.initiatedThe converted crypto leg was initiated toward the destination wallet.
virtualAccount.cryptoTransfer.pendingThe crypto leg is in flight.
virtualAccount.cryptoTransfer.settledThe crypto leg was delivered.
virtualAccount.cryptoTransfer.failedThe crypto leg failed.

Deposit addresses

Lifecycle events use the depositAddress. prefix; per-deposit and per-payout legs use the deposit_address. prefix.
EventFires when
depositAddress.createdThe deposit address record was created.
depositAddress.activeThe inlet address is provisioned and monitoring; depositInstructions is populated.
depositAddress.paused / depositAddress.resumedMonitoring was paused or resumed.
depositAddress.frozenDeposits are held pending review.
depositAddress.closedThe address reached end of life.
depositAddress.deletedThe record was removed.
depositAddress.failedProvisioning failed.
deposit_address.crypto_deposit.pendingAn inbound on-chain deposit was detected.
deposit_address.crypto_deposit.settledThe inbound deposit settled.
deposit_address.crypto_deposit.failedThe inbound deposit failed.
deposit_address.crypto_deposit.needs_attributionThe deposit came from an unrecognized sender and is held for sender attribution.
deposit_address.ach_payout.initiated / .pending / .settled / .failed / .returnedThe ACH payout leg progressed.
deposit_address.wire_payout.initiated / .pending / .settled / .failed / .returnedThe domestic wire payout leg progressed.
deposit_address.intl_wire_payout.initiated / .pending / .settled / .failed / .returnedThe international wire payout leg progressed.

External accounts

EventFires when
externalAccount.createdThe account was registered and is being validated.
externalAccount.verifiedValidation passed; the account is usable on quotes.
externalAccount.declinedValidation failed.
externalAccount.deletedThe account was removed.

Endorsements

EventFires when
endorsement.updatedA customer endorsement changed state.
endorsement.activeAn endorsement became active; the customer can use the operations it gates.

Wallets

EventFires when
wallet.provisionedA custodial wallet’s on-chain address was provisioned.
wallet.depositDetectedCrypto arrived at a wallet address outside any OMS-initiated transaction.

Delivery and verification

  • Deliveries are signed with the Webhook-Signature header (t=<unix>,v1=<hex>, an HMAC-SHA256 over <timestamp>.<raw-body> with your per-endpoint signing secret). Verify before processing and reject stale timestamps.
  • Deliveries can arrive more than once and, across different resources, out of order. Deduplicate on eventId and use sequence to order events about the same resource.
  • Manage subscriptions with the Webhooks endpoints: POST/GET /webhooks, GET/PATCH/DELETE /webhooks/{id}.