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

# Withdrawal webhooks

> Receive a signed event when a fiat or stablecoin withdrawal is processing, completes, or fails. Event envelope and Withdrawal resource shape.

OpenFX delivers a signed webhook event when a withdrawal transitions to a notable state. Three event types cover the withdrawal lifecycle:

* **`withdrawal.processing`** — the withdrawal has been accepted and is moving through the payment rail.
* **`withdrawal.completed`** — the withdrawal has settled successfully.
* **`withdrawal.failed`** — the withdrawal has reached a terminal failure state.

All three event types carry a single Withdrawal object in `data` that follows the same field conventions as v3 REST API responses — camelCase fields, string amounts, RFC 3339 timestamps. The `data` object matches what [`GET /v3/fx/withdrawals/{id}`](/v3/api-reference/trade-settlement/get-withdrawal) returns for the same record.

## Event envelope

This routing-only example collapses `data` to an empty object. It deliberately omits the required Withdrawal fields shown in the complete, schema-checked examples below.

```json theme={null}
{
  "id": "evt_7m4VsfRw4pGrS76WYj5tnx",
  "type": "withdrawals",
  "eventType": "withdrawal.completed",
  "createdAt": "2026-04-28T08:32:50.618Z",
  "data": {}
}
```

| Field       | Type                                | Notes                                                                                            |
| ----------- | ----------------------------------- | ------------------------------------------------------------------------------------------------ |
| `id`        | string (readable ID, `evt_` prefix) | Unique per event. Deduplicate on this field.                                                     |
| `type`      | string                              | Resource noun: always `"withdrawals"` for withdrawal events. Use it to route by resource family. |
| `eventType` | string                              | Dotted action: `"withdrawal.processing"`, `"withdrawal.completed"`, or `"withdrawal.failed"`.    |
| `createdAt` | string (RFC 3339, ms, UTC)          | When OpenFX created the event.                                                                   |
| `data`      | object                              | The Withdrawal resource in its current state. See field reference below.                         |

## Payload

<Tabs>
  <Tab title="Fiat (Fedwire / SEPA / SWIFT / ACH)">
    ```json theme={null}
    {
      "id": "evt_7m4VsfRw4pGrS76WYj5tnx",
      "type": "withdrawals",
      "eventType": "withdrawal.completed",
      "createdAt": "2026-04-28T08:32:50.618Z",
      "data": {
        "object": "withdrawal",
        "id": "wtd_6SATV6VSUdBTttHWBmCYjD",
        "currency": "USD",
        "assetType": "FIAT",
        "withdrawalAmount": "5000.00",
        "status": "COMPLETED",
        "network": null,
        "withdrawalAccountId": "wac_NDqQ9LmcUASpnHR6CTvdkk",
        "estimatedCompletionAt": null,
        "transactionHash": null,
        "paymentDetails": {
          "FEDWIRE": {
            "imad": "20260428B1QGC07C001234",
            "omad": "20260428L1B7012C003456"
          }
        },
        "actorId": "usr_7m4VsfRw4pGrS76WYj5tnx",
        "actorEmail": "client-user@example.com",
        "comments": "Invoice 1042",
        "createdAt": "2026-04-28T08:28:05.112Z"
      }
    }
    ```

    | Field                    | Notes                                                                                                                                                                      |
    | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `assetType`              | `"FIAT"` for bank-rail withdrawals.                                                                                                                                        |
    | `network`                | `null` for fiat withdrawals — there is no chain to read.                                                                                                                   |
    | `withdrawalAccountId`    | Readable ID (`wac_` prefix) of the verified withdrawal account this payment was sent to.                                                                                   |
    | `paymentDetails`         | Network-specific identifiers populated once the withdrawal reaches a terminal state, keyed by transfer type (e.g. `FEDWIRE` IMAD/OMAD). Present only for fiat withdrawals. |
    | `actorId` / `actorEmail` | Identify who initiated the withdrawal. Masked to a fixed placeholder when the actor is an internal OpenFX operator.                                                        |
    | `comments`               | Optional notes recorded with the withdrawal. `null` when none were recorded.                                                                                               |
    | `withdrawalAmount`       | String decimal — e.g. `"5000.00"`. Always positive.                                                                                                                        |
  </Tab>

  <Tab title="Stablecoin (USDC / USDT / EURC)">
    ```json theme={null}
    {
      "id": "evt_7m4VsfRw4pGrS76WYj5tnx",
      "type": "withdrawals",
      "eventType": "withdrawal.completed",
      "createdAt": "2026-04-28T08:32:50.618Z",
      "data": {
        "object": "withdrawal",
        "id": "wtd_6SATV6VSUdBTttHWBmCYjD",
        "currency": "USDT",
        "assetType": "CRYPTO",
        "withdrawalAmount": "10000.00",
        "status": "COMPLETED",
        "network": "ETHEREUM",
        "withdrawalAccountId": "wac_NDqQ9LmcUASpnHR6CTvdkk",
        "estimatedCompletionAt": null,
        "transactionHash": "0xdef456abc7890123def456abc7890123def456abc7890123def456abc78901",
        "paymentDetails": null,
        "actorId": "usr_7m4VsfRw4pGrS76WYj5tnx",
        "actorEmail": "client-user@example.com",
        "comments": null,
        "createdAt": "2026-04-28T08:28:05.112Z"
      }
    }
    ```

    | Field              | Notes                                                                                                                        |
    | ------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
    | `network`          | The chain the withdrawal settled over (e.g. `ETHEREUM`, `SOLANA`, `TRON`; see [Supported networks](/v3/supported-networks)). |
    | `transactionHash`  | The on-chain transaction hash once broadcast. `null` before the chain leg lands.                                             |
    | `paymentDetails`   | `null` for crypto withdrawals — populated only for fiat.                                                                     |
    | `withdrawalAmount` | String decimal. Always positive.                                                                                             |
  </Tab>
</Tabs>

<Note>
  `status` is an unconstrained string reflecting the current lifecycle state (no
  closed enum is documented) — observed values include `PENDING`, `PROCESSING`,
  `COMPLETED`, `FAILED`, `RETURNED`, and `CANCELED`. The webhook catalog ships
  `withdrawal.processing`, `withdrawal.completed`, and `withdrawal.failed`
  events; the v3 API surfaces the same record with a matching status via [`GET
      /v3/fx/withdrawals/{id}`](/v3/api-reference/trade-settlement/get-withdrawal).
</Note>

## Withdrawal resource fields

| Field                   | Type                                | Notes                                                                                                                                                                        |
| ----------------------- | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `object`                | string                              | Always `"withdrawal"`.                                                                                                                                                       |
| `id`                    | string (readable ID, `wtd_` prefix) | Withdrawal resource ID.                                                                                                                                                      |
| `currency`              | string                              | ISO 4217 currency code or stablecoin ticker.                                                                                                                                 |
| `assetType`             | string                              | Asset class: `"CRYPTO"` for on-chain, `"FIAT"` for bank rails.                                                                                                               |
| `withdrawalAmount`      | string                              | Decimal string, e.g. `"5000.00"`. Always positive.                                                                                                                           |
| `status`                | string                              | Unconstrained lifecycle state string; no closed enum is documented.                                                                                                          |
| `network`               | string \| null                      | Network the crypto withdrawal settled over, e.g. `ETHEREUM`. `null` for fiat withdrawals.                                                                                    |
| `withdrawalAccountId`   | string (readable ID, `wac_` prefix) | References the `WithdrawalAccount.id` this withdrawal pays to.                                                                                                               |
| `estimatedCompletionAt` | string \| null (RFC 3339, ms, UTC)  | When the withdrawal is expected to settle. `null` if there is no ETA yet.                                                                                                    |
| `transactionHash`       | string \| null                      | On-chain transaction hash for crypto withdrawals once broadcast. `null` for fiat or before the chain leg lands.                                                              |
| `paymentDetails`        | object \| null                      | Network-specific identifiers populated once the withdrawal reaches a terminal state, keyed by transfer type. Present only for fiat withdrawals; omitted entirely for crypto. |
| `actorId`               | string (readable ID, `usr_` prefix) | ID of the actor that initiated the withdrawal. Masked to a fixed placeholder when the actor is an internal OpenFX operator.                                                  |
| `actorEmail`            | string                              | Email of the actor that initiated the withdrawal. Masked to a fixed placeholder when the actor is an internal OpenFX operator.                                               |
| `comments`              | string \| null                      | Optional notes or comments about the withdrawal. `null` when none were recorded.                                                                                             |
| `createdAt`             | string (RFC 3339, ms, UTC)          | When the withdrawal record was created.                                                                                                                                      |
| `metadata`              | object                              | Only present when you supplied `metadata` on the originating `POST /v3/fx/withdrawals` request. See [Withdrawal metadata](/v3/metadata-and-tracing#withdrawal-metadata).     |

## Idempotency on your side

Same pattern as deposit webhooks — use the event `id` for dedup. See [Deposit webhooks: idempotency on your side](/v3/webhooks/deposits#idempotency-on-your-side).

## Failed withdrawals

When a withdrawal terminates as `FAILED`, the `withdrawal.failed` event is delivered with `data.status: "FAILED"`. If you need the latest state — for example to confirm a subsequent `RETURNED`, or after a missed delivery — re-fetch with [`GET /v3/fx/withdrawals/{id}`](/v3/api-reference/trade-settlement/get-withdrawal) using the `id` from `data.id`. See [Withdrawal lifecycle: when a withdrawal is stuck](/v3/withdrawal-lifecycle#when-a-withdrawal-is-stuck) for the triage runbook.

## Verification

Every event is signed in the `X-OpenFX-Signature` header using HMAC-SHA256 over the signed payload `timestamp + "." + raw_body`. Always verify with a constant-time comparator before reading any payload field. See [Webhook authentication](/v3/webhooks/authentication).

## What's next

<CardGroup cols={2}>
  <Card title="Webhook authentication" icon="lock" href="/v3/webhooks/authentication">
    Signature verification with constant-time comparators.
  </Card>

  <Card title="Deposit webhooks" icon="arrow-down-to-bracket" href="/v3/webhooks/deposits">
    The other side of the deposit/withdrawal lifecycle.
  </Card>

  <Card title="Withdrawal lifecycle" icon="arrow-up-from-bracket" href="/v3/withdrawal-lifecycle">
    State machine + stuck-withdrawal runbook.
  </Card>

  <Card title="Errors" icon="triangle-exclamation" href="/v3/errors">
    Stable error codes and the retry triage matrix.
  </Card>
</CardGroup>
