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

# Failures and refunds

> The two ways a Flow payment can go wrong, the failure codes a flow reports, how refunds are reported, and what to show the payer.

Something can go wrong in two different ways during a Flow payment. A request can be rejected, which leaves the flow as it was, or the flow itself can fail, which ends it. This page explains both, lists the failure codes a flow reports, and describes how refunds work.

## Rejected requests and failed flows

| What happened | Example | Flow state | What to do |
| - | - | - | - |
| A request is rejected | The quote expired, the wallet was blocked by screening, or the request is not valid from the current state | Unchanged | Read the flow, then continue from its current state |
| The flow fails | The transaction reverted, or conversion failed | `failed` on execution or settlement | The flow is final. Create a new flow if the payer should try again |

A rejected request is something the payer or your UI can usually recover from in the same flow, for example by requesting a new quote or choosing another source. The [API guide](https://www.dynamic.xyz/docs/flow/api.md) and the SDK references list the errors each request can return.

A failed flow cannot be retried. Its `executionState` or `settlementState` is `failed`, and its `failure` field describes the reason.

## The failure record

A failed flow carries a `failure` object with these fields:

| Field | Meaning |
| - | - |
| `code` | The reason, from the table in [Failure codes](#failure-codes) |
| `message` | A human-readable description |
| `category` | The kind of failure, such as `refund` for the two refund codes |
| `stage` | Where the payment was when it failed |
| `retryable` | Always `false`. A failed flow cannot continue |

Your server receives the same record in the `failed` execution webhook and in the settlement webhook when settlement fails.

## Failure codes

| `code` | What it means | What to do |
| - | - | - |
| `AMOUNT_MISMATCH` | The payment that arrived did not match the quote, for example a different token or a smaller amount | Tell the payer the payment did not match, and contact support if funds were sent |
| `TX_REVERTED` | The payer's transaction failed on chain | Create a new flow if the payer wants to try again |
| `SUBMISSION_FAILED` | The payment never went through: the transaction did not reach the chain, or the exchange purchase failed | Create a new flow if the payer wants to try again |
| `BRIDGE_FAILED` | Conversion or delivery failed, and no refund was reported | Contact support |
| `REFUND_INITIATED` | The provider started returning the funds to the payer | Tell the payer a refund was started |
| `REFUND_FAILED` | The provider could not return the funds | Contact support |
| `MAX_POLLING_RETRIES` | Dynamic could not confirm the outcome in time, so the outcome is unknown | Contact support before telling the payer the payment failed |
| `INTERNAL_ERROR` | An internal error stopped the payment | Contact support |

Treat a code your integration does not recognize as a failure, and show the `message`.

## Refunds

Refunds in Flow payments are performed by the provider that handled the payment, such as the deposit-address or conversion provider. Dynamic does not initiate refunds.

* `REFUND_INITIATED` means the provider reported that it started returning the funds. For a deposit address, the funds go to the refund address the payer gave.
* `REFUND_FAILED` means the provider reported that the refund failed. The funds were not returned, and you need to contact support to resolve it.

Never tell a payer that a refund is guaranteed before the flow reports `REFUND_INITIATED`.

Funds sent to a deposit address after the flow was cancelled or expired have no provider refund. They can still reach your destination, the flow does not record them, and no webhook reports them, so you handle any refund to the payer. See [Expiry and cancellation](https://www.dynamic.xyz/docs/flow/expiry-and-cancellation.md#funds-sent-after-cancellation-or-expiry).

A short payment in `deposit` mode is not a failure and is not refunded: the flow settles for the amount that arrived. See [Short payments depend on the mode](https://www.dynamic.xyz/docs/flow/lifecycle-walkthrough.md#short-payments-depend-on-the-mode).

## What to show the payer

Check the flow in this order and show the first outcome that applies:

1. `settlementState` is `completed`: the payment succeeded. Show the delivered amount when the flow reports one.
2. Either axis is `failed`: show the failure. When `failure.code` is `REFUND_INITIATED`, show that a refund was started.
3. `executionState` is `cancelled`: the payment was cancelled.
4. `executionState` is `expired`: the payment expired. A new payment needs a new flow.
5. Any other state: the payment is still in progress.

## Next

> **[Payment lifecycle and states](https://www.dynamic.xyz/docs/flow/lifecycle-walkthrough.md)**
>
> Every state and what moves a flow between them.

> **[Webhooks](https://www.dynamic.xyz/docs/flow/webhooks.md)**
>
> How your server learns that a flow failed.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.