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

# Webhooks and events

> How a flow reports its own progress across three independent axes, and how to reconcile a completed payment against your records.

A flow reports progress through signed webhooks that fire at every lifecycle transition. Polling works too, but webhooks are the path that scales: a flow can sit in settlement for a while, and polling it is wasted work.

Every payload is HMAC-signed, so your backend can verify an event came from Dynamic before acting on it.

## Three axes, three event types

A flow does not have one status. It has three, and they move independently. That is the single most useful thing to understand about the event model, because a flow can be finished on one axis and still in progress on another.

| Event              | Axis                       | Example progression                                                                         |
| ------------------ | -------------------------- | ------------------------------------------------------------------------------------------- |
| Execution updated  | What the payer has done    | `initiated` → `source_attached` → `quoted` → `signing` → `broadcasted` → `source_confirmed` |
| Settlement updated | What Dynamic has delivered | `none` → `routing` → `completed`                                                            |
| Risk updated       | What compliance concluded  | `unknown` → `cleared`                                                                       |

Each event carries both the previous and the new state, so your backend can react to a specific transition rather than re-deriving what changed.

<Warning>
  Execution reaching `source_confirmed` does not mean the money has landed. Settlement can still be routing. Treat settlement as the axis that tells you a payment is done.
</Warning>

## Reconciling a completed payment

When settlement reaches `completed`, the event carries the on-chain transaction hash that delivered the funds to your destination. Paired with the flow's [memo](/docs/flow/settlements#memos-and-reconciliation), that is everything needed to match a payment against an internal order or treasury record.

The same payload carries the destination chain name and ID, plus block explorer URLs, so you can link a customer straight to their transaction without assembling explorer URLs yourself.

## Choosing webhooks or polling

Polling is simpler to stand up and fine for a prototype or a low-volume flow. Webhooks are the right default in production: they remove the latency of a poll interval, they cost nothing while a flow is idle, and they deliver the settlement transaction hash without an extra read.

Nothing stops you doing both. A webhook-driven backend that also reconciles by polling on a schedule is a reasonable belt-and-braces posture for payments.

## Flow event payloads

Flow events send a **state-transition payload**, not the full flow object. Use the `flowId` with [`getFlow`](/docs/javascript/reference/client/get-flow) to fetch the full flow state. See the [Flow API guide](/docs/flow/api) for details on each state.

<ParamField body="flow.execution.updated" type="object">
  Occurs whenever a flow's execution state changes. The payload includes `previousState` and `newState`: for example `initiated` → `source_attached`, `signing` → `broadcasted`, or `broadcasted` → `failed`. Possible execution states: `initiated`, `source_attached`, `quoted`, `signing`, `broadcasted`, `source_confirmed`, `cancelled`, `expired`, `failed`.
</ParamField>

<ParamField body="flow.settlement.updated" type="object">
  Occurs whenever a flow's settlement state changes. Settlement tracks the post-broadcast movement of funds. `data.additionalData` identifies the destination chain the settlement lands on with `chainName` (for example `SOL` or `EVM`) and `chainId` (a string, for example `"101"`). When the new state is `completed`, it also includes `settlementTxHash` (the on-chain transaction hash that delivered the settled funds) and `blockExplorerUrls` (explorer links for that transaction). Possible settlement states: `none`, `routing`, `bridging`, `swapping`, `settling`, `completed`, `failed`.
</ParamField>

<ParamField body="flow.risk.updated" type="object">
  Occurs whenever a flow's risk assessment state changes. Fired when risk screening transitions, for example `unknown` → `pending` → `cleared`. Possible risk states: `unknown`, `pending`, `cleared`, `blocked`, `review`.
</ParamField>

#### Example Flow Event Payload

```json theme={"system"}
{
  "eventId": "2a92c161-3167-44ad-8fce-4c6cdaed8129",
  "messageId": "5a2a5360-bb7e-4ea6-9bd3-0146bf2f734f",
  "webhookId": "a86acea4-e050-4846-8e4f-0ae039f6e37c",
  "userId": "a5914498-7a8b-4c58-b04c-9624fef2897c",
  "externalUserId": "usr_abc123",
  "eventName": "flow.execution.updated",
  "environmentId": "123e4567-e89b-12d3-a456-426614174000",
  "environmentName": "live",
  "timestamp": "2026-06-15T12:00:00.000Z",
  "data": {
    "axis": "execution",
    "flowId": "fl_abc123",
    "previousState": "initiated",
    "newState": "source_attached",
    "timestamp": "2026-06-15T12:00:00.000Z",
    "additionalData": {
      "fromAddress": "0x3FcE1F4F28DbA209344072867134A3a7F547C7f1",
      "fromChainId": "1",
      "sourceType": "wallet"
    }
  }
}
```

#### Example Flow Settlement Completed Payload

```json theme={"system"}
{
  "eventId": "2a92c161-3167-44ad-8fce-4c6cdaed8129",
  "messageId": "5a2a5360-bb7e-4ea6-9bd3-0146bf2f734f",
  "webhookId": "a86acea4-e050-4846-8e4f-0ae039f6e37c",
  "userId": "a5914498-7a8b-4c58-b04c-9624fef2897c",
  "externalUserId": "usr_abc123",
  "eventName": "flow.settlement.updated",
  "environmentId": "123e4567-e89b-12d3-a456-426614174000",
  "environmentName": "live",
  "timestamp": "2026-06-15T12:00:00.000Z",
  "data": {
    "axis": "settlement",
    "flowId": "fl_abc123",
    "previousState": "settling",
    "newState": "completed",
    "timestamp": "2026-06-15T12:00:00.000Z",
    "additionalData": {
      "chainName": "SOL",
      "chainId": "101",
      "blockExplorerUrls": [
        "https://explorer.solana.com/tx/3Eru8qQQdM6zc4jYgaUZPMxQn6ZhBPzy9gJBzZUje45ufijNAFHMqZSDmxTitXQgp4px9xoLd6oP3BnhCK2t1QJZ"
      ],
      "completedAt": "2026-06-15T12:00:00.000Z",
      "settlementTxHash": "3Eru8qQQdM6zc4jYgaUZPMxQn6ZhBPzy9gJBzZUje45ufijNAFHMqZSDmxTitXQgp4px9xoLd6oP3BnhCK2t1QJZ"
    }
  }
}
```

Use `settlementTxHash` with `chainName` and `chainId` to reconcile the completed flow against the destination-chain transaction, and `blockExplorerUrls` to link your users straight to it. Pair the hash with the flow `memo` to match the settlement to an internal order or invoice.

<Note>
  Fields with nothing to report are omitted rather than sent as `null`. `chainName` and `chainId` are absent until the flow has a destination chain, and `blockExplorerUrls` is absent when the settlement has no transaction hash yet or the destination network has no configured explorer.
</Note>

## Exchange transfer events

<ParamField body="user.exchangeTransfer.success" type="object">
  Occurs whenever an exchange transfer is successfully initiated. Is an
  [ExchangeTransferResponse.](/docs/api-reference/schemas/ExchangeTransferResponse)
</ParamField>

<ParamField body="user.exchangeTransfer.failed" type="object">
  Occurs whenever an exchange transfer fails for any reason. Contains error details
  about the failure.
</ParamField>

## Legacy checkout events

<Note>
  Checkout transaction events apply to the legacy checkout system. For new integrations, use [Fireblocks Flow](/docs/flow/overview) and subscribe to `flow.*` events instead.
</Note>

Checkout transaction events send a **state-transition payload**, not the full transaction. Use the `transactionId` with [`getFlow`](/docs/javascript/reference/client/get-flow) to fetch the full flow state.

<ParamField body="checkout.transaction.execution.updated" type="object">
  Occurs whenever a checkout transaction's execution state changes. The execution state tracks how the transaction is moving through the payment lifecycle: for example `initiated`, `source_attached`, `quoted`, `signing`, `broadcasted`, `failed`, `cancelled`, or `expired`.
</ParamField>

<ParamField body="checkout.transaction.settlement.updated" type="object">
  Occurs whenever a checkout transaction's settlement state changes. The settlement state tracks the post-broadcast flow of funds: for example `none`, `routing`, `bridging`, `swapping`, `settling`, `completed`, or `failed`.
</ParamField>

<ParamField body="checkout.transaction.risk.updated" type="object">
  Occurs whenever a checkout transaction's risk assessment state changes. Fired when risk screening transitions between states such as `unknown`, `cleared`, or `blocked`.
</ParamField>

#### Example Checkout Event Payload

```json theme={"system"}
{
  "eventId": "2a92c161-3167-44ad-8fce-4c6cdaed8129",
  "messageId": "5a2a5360-bb7e-4ea6-9bd3-0146bf2f734f",
  "webhookId": "a86acea4-e050-4846-8e4f-0ae039f6e37c",
  "userId": "a5914498-7a8b-4c58-b04c-9624fef2897c",
  "externalUserId": "usr_abc123",
  "eventName": "checkout.transaction.execution.updated",
  "environmentId": "123e4567-e89b-12d3-a456-426614174000",
  "environmentName": "sandbox",
  "timestamp": "2023-10-26T14:30:59.210Z",
  "data": {
    "axis": "execution",
    "previousState": "initiated",
    "newState": "source_attached",
    "transactionId": "484e49ba-3026-4e2c-9bf0-ed98ae224833",
    "timestamp": "2023-10-26T14:30:59.210Z",
    "additionalData": {
      "fromAddress": "0x3FcE1F4F28DbA209344072867134A3a7F547C7f1",
      "fromChainId": "1",
      "sourceType": "wallet"
    }
  }
}
```

## Next

<Columns cols={2}>
  <Card title="Webhook setup" href="/docs/platform/dashboard/webhooks/setup">
    Configuring endpoints and verifying signatures.
  </Card>

  <Card title="Delivery best practices" href="/docs/platform/dashboard/webhooks/delivery-best-practices">
    Retries, idempotency, and signature verification.
  </Card>
</Columns>
