> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polygon.technology/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhook events

> The catalog of webhook events OMS delivers, and the envelope every event arrives in.

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.

| Field             | Type      | Description                                                                                               |
| ----------------- | --------- | --------------------------------------------------------------------------------------------------------- |
| `eventId`         | string    | Unique, stable ID for this event. Use it to deduplicate retried deliveries.                               |
| `eventName`       | string    | The event type from the catalog below.                                                                    |
| `schemaVersion`   | integer   | Envelope schema version.                                                                                  |
| `producerService` | string    | The OMS service that produced the event.                                                                  |
| `orgId`           | string    | Your organization.                                                                                        |
| `projectId`       | string    | The project the event belongs to. Optional.                                                               |
| `customerId`      | string    | The customer the resource belongs to, when applicable. Optional.                                          |
| `mode`            | string    | The environment the event was produced in. Optional.                                                      |
| `resourceType`    | string    | The kind of resource in `payload` (for example `cashIn`, `virtualAccount`, `transaction_crypto_to_fiat`). |
| `resourceId`      | string    | The ID of the resource in `payload`.                                                                      |
| `sequence`        | integer   | Monotonic sequence for ordering events about the same resource. Optional.                                 |
| `occurredAt`      | timestamp | When the event occurred.                                                                                  |
| `correlationId`   | string    | Correlates events produced by the same logical operation. Optional.                                       |
| `causationId`     | string    | The event that caused this one, when applicable. Optional.                                                |
| `payload`         | object    | The full resource object at the time of the event.                                                        |

```json theme={null}
{
  "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](/payments/guides/crypto-to-fiat#returns-and-refunds)).

| Event                                        | Fires when                                                  |
| -------------------------------------------- | ----------------------------------------------------------- |
| `transaction.fiatToCrypto.processing`        | A fiat-funded transaction starts executing.                 |
| `transaction.fiatToCrypto.completed`         | Crypto delivered to the destination.                        |
| `transaction.fiatToCrypto.failed`            | The transaction failed; see `payload.error`.                |
| `transaction.fiatToCrypto.refundCompleted`   | The refund for a failed transaction was delivered.          |
| `transaction.fiatToCrypto.refundFailed`      | The refund itself failed; operator follow-up.               |
| `transaction.cryptoToFiat.processing`        | A crypto-funded payout starts executing.                    |
| `transaction.cryptoToFiat.cashPickupReady`   | Cash payout only: the pickup code was issued.               |
| `transaction.cryptoToFiat.codeExpired`       | Cash payout only: the pickup code expired uncollected.      |
| `transaction.cryptoToFiat.completed`         | Fiat delivered to the destination.                          |
| `transaction.cryptoToFiat.failed`            | The payout failed; see `payload.error`.                     |
| `transaction.cryptoToFiat.refundCompleted`   | The stablecoin re-credit for a failed payout was delivered. |
| `transaction.cryptoToFiat.refundFailed`      | The re-credit itself failed; operator follow-up.            |
| `transaction.cryptoToCrypto.processing`      | A crypto-to-crypto send starts executing.                   |
| `transaction.cryptoToCrypto.completed`       | Crypto delivered to the destination.                        |
| `transaction.cryptoToCrypto.failed`          | The send failed; see `payload.error`.                       |
| `transaction.cryptoToCrypto.refundCompleted` | The refund for a failed send was delivered.                 |
| `transaction.cryptoToCrypto.refundFailed`    | The refund itself failed; operator follow-up.               |

## Cash-in

| Event              | Fires when                                                                                   |
| ------------------ | -------------------------------------------------------------------------------------------- |
| `cashIn.created`   | A cash-in code was issued.                                                                   |
| `cashIn.completed` | The cash was deposited and converted; the auto-created transaction is linked on the cash-in. |
| `cashIn.expired`   | The code expired before a deposit was made.                                                  |

## Virtual accounts

| Event                                     | Fires when                                                                  |
| ----------------------------------------- | --------------------------------------------------------------------------- |
| `virtualAccount.created`                  | The virtual account record was created.                                     |
| `virtualAccount.provisioned`              | The underlying deposit account was provisioned; `bankDetails` is populated. |
| `virtualAccount.active`                   | The account is live and accepting deposits.                                 |
| `virtualAccount.frozen`                   | Deposits are suspended.                                                     |
| `virtualAccount.closed`                   | The account reached end of life.                                            |
| `virtualAccount.deleted`                  | An asynchronous delete finalized.                                           |
| `virtualAccount.failed`                   | Provisioning failed.                                                        |
| `virtualAccount.deposit.pending`          | An inbound bank deposit was detected and is settling.                       |
| `virtualAccount.deposit.settled`          | The inbound deposit settled.                                                |
| `virtualAccount.deposit.failed`           | The inbound deposit failed.                                                 |
| `virtualAccount.deposit.returned`         | The inbound deposit was returned by the bank.                               |
| `virtualAccount.cryptoTransfer.initiated` | The converted crypto leg was initiated toward the destination wallet.       |
| `virtualAccount.cryptoTransfer.pending`   | The crypto leg is in flight.                                                |
| `virtualAccount.cryptoTransfer.settled`   | The crypto leg was delivered.                                               |
| `virtualAccount.cryptoTransfer.failed`    | The crypto leg failed.                                                      |

## Deposit addresses

Lifecycle events use the `depositAddress.` prefix; per-deposit and per-payout legs use the `deposit_address.` prefix.

| Event                                                                                            | Fires when                                                                                                                           |
| ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| `depositAddress.created`                                                                         | The deposit address record was created.                                                                                              |
| `depositAddress.active`                                                                          | The inlet address is provisioned and monitoring; `depositInstructions` is populated.                                                 |
| `depositAddress.paused` / `depositAddress.resumed`                                               | Monitoring was paused or resumed.                                                                                                    |
| `depositAddress.frozen`                                                                          | Deposits are held pending review.                                                                                                    |
| `depositAddress.closed`                                                                          | The address reached end of life.                                                                                                     |
| `depositAddress.deleted`                                                                         | The record was removed.                                                                                                              |
| `depositAddress.failed`                                                                          | Provisioning failed.                                                                                                                 |
| `deposit_address.crypto_deposit.pending`                                                         | An inbound on-chain deposit was detected.                                                                                            |
| `deposit_address.crypto_deposit.settled`                                                         | The inbound deposit settled.                                                                                                         |
| `deposit_address.crypto_deposit.failed`                                                          | The inbound deposit failed.                                                                                                          |
| `deposit_address.crypto_deposit.needs_attribution`                                               | The deposit came from an unrecognized sender and is held for [sender attribution](/payments/guides/deposit-addresses#held-deposits). |
| `deposit_address.ach_payout.initiated` / `.pending` / `.settled` / `.failed` / `.returned`       | The ACH payout leg progressed.                                                                                                       |
| `deposit_address.wire_payout.initiated` / `.pending` / `.settled` / `.failed` / `.returned`      | The domestic wire payout leg progressed.                                                                                             |
| `deposit_address.intl_wire_payout.initiated` / `.pending` / `.settled` / `.failed` / `.returned` | The international wire payout leg progressed.                                                                                        |

## External accounts

| Event                      | Fires when                                          |
| -------------------------- | --------------------------------------------------- |
| `externalAccount.created`  | The account was registered and is being validated.  |
| `externalAccount.verified` | Validation passed; the account is usable on quotes. |
| `externalAccount.declined` | Validation failed.                                  |
| `externalAccount.deleted`  | The account was removed.                            |

## Endorsements

| Event                 | Fires when                                                                  |
| --------------------- | --------------------------------------------------------------------------- |
| `endorsement.updated` | A customer endorsement changed state.                                       |
| `endorsement.active`  | An endorsement became active; the customer can use the operations it gates. |

## Wallets

| Event                    | Fires when                                                                |
| ------------------------ | ------------------------------------------------------------------------- |
| `wallet.provisioned`     | A custodial wallet's on-chain address was provisioned.                    |
| `wallet.depositDetected` | Crypto 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](/api-reference/overview): `POST`/`GET /webhooks`, `GET`/`PATCH`/`DELETE /webhooks/{id}`.
