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

# Operation failures

> Distinguish HTTP errors from terminal Payment, Refund, and Payout outcomes

An HTTP request can succeed while the created financial object later reaches a
failed state. Handle transport and request failures separately from object
status.

## Four failure surfaces

* **HTTP error:** no successful operation response was returned. Use
  `error.code` and the [HTTP error catalogue](/guides/errors). If retrying a
  create operation, preserve the original `Idempotency-Key` and an equivalent
  operation-specific effective request identity unless the catalogue requires
  a corrected request. Keep card-data retries inside the approved PCI boundary.
* **Payment FAILED:** the create call may have returned `201`. Use the
  Payment's `failure_code` and `failure_message`. This Payment is final; a
  customer retry creates a new Payment with a new key.
* **Refund FAILED:** the Refund exists. Use `failure.code` and
  `failure.message`, retrieve the parent Payment, and check the remaining
  refundable amount and business intent before creating a new Refund.
* **Payout FAILED:** the Payout is terminal. Use its public `failure_code`
  and `failure_message`, retain the Payout ID and request ID, and reconcile
  the result before deciding on a distinct business Payout.

## Payment and Refund failure codes

Payment `failure_code` and Refund `failure.code` use the same public vocabulary
below. The meaning column applies to both objects; the action column applies
only to a failed Payment. Do not apply that Payment action to a Refund. Keep
customer-facing text short and neutral. A Refund never requires a shopper
browser action: if a Refund carries a 3D Secure-labelled terminal code, treat
it only as a failure reason and do not redirect the customer.

| `failure_code`                 | Meaning                                                      | Merchant action for a failed Payment                         |
| ------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| `not_found`                    | A required payment operation could not be found.             | Retain the Payment and request IDs and contact support.      |
| `processor_error`              | The processor returned a transient processing failure.       | Create a new Payment after a short delay.                    |
| `processor_unavailable`        | The processor was temporarily unavailable.                   | Create a new Payment later.                                  |
| `generic_decline`              | The card was declined without a more specific public reason. | Ask for another card.                                        |
| `do_not_honor`                 | The issuer declined the transaction.                         | Ask for another card.                                        |
| `issuer_declined`              | The issuer declined the transaction.                         | Ask for another card.                                        |
| `insufficient_funds`           | Available funds were insufficient.                           | Ask the customer to use another card or resolve the balance. |
| `invalid_number`               | The card number was invalid.                                 | Let the customer correct it or use another card.             |
| `invalid_expiry`               | The expiry value was invalid.                                | Let the customer correct it or use another card.             |
| `expired_card`                 | The card has expired.                                        | Ask for another card.                                        |
| `invalid_amount`               | The amount was invalid for this payment method.              | Check the integration before a new attempt.                  |
| `invalid_currency`             | The currency was invalid for this payment method.            | Check the integration before a new attempt.                  |
| `not_permitted`                | The transaction is not permitted for this card.              | Ask for another card.                                        |
| `cardholder_limit`             | A cardholder limit was exceeded.                             | Ask for another card or let the customer resolve the limit.  |
| `card_velocity_exceeded`       | A card activity limit was exceeded.                          | Ask for another card or try later as a new attempt.          |
| `lost_card`                    | The card was reported lost.                                  | Show only a generic decline and ask for another card.        |
| `stolen_card`                  | The card was reported stolen.                                | Show only a generic decline and ask for another card.        |
| `suspect_fraud`                | The issuer or processor suspected fraud.                     | Show only a generic decline and ask for another card.        |
| `fraud_filter`                 | Fraud controls declined the Payment.                         | Show only a generic decline and ask for another card.        |
| `three_d_secure_failed`        | 3D Secure authentication failed.                             | If the customer retries, create a new Payment.               |
| `three_d_secure_timeout`       | 3D Secure authentication timed out.                          | If the customer retries, create a new Payment.               |
| `three_d_secure_not_supported` | The card cannot complete the required 3D Secure flow.        | Ask for another card.                                        |
| `three_d_secure_error`         | 3D Secure could not be completed.                            | If the customer retries, create a new Payment.               |

An unknown `failure_code` is still a terminal Payment failure. Show a neutral
decline, offer another card, retain the IDs, and do not expose raw processor
details.

## Refund failures

When a Refund is `FAILED`, use the nested `failure.code` and `failure.message`
for developer handling. The Refund object remains part of the parent Payment's
`refunds[]` history. Never ask for another card or initiate a browser action
from the shared failure code. An unknown `failure.code` is still a terminal
Refund failure: retain the Refund, Payment, and request IDs, show neutral text,
and reconcile the parent Payment before deciding whether to create another
Refund. Before another Refund:

1. retrieve the parent Payment;
2. reconcile `amount_refunded` and `amount_refundable`;
3. confirm that the business still intends to return the amount;
4. create a distinct Refund with a new key only when appropriate.

## Payout failures

`FAILED` records a definitive Payout failure. Read `failure_code` and
`failure_message`; these fields are omitted in other states. They use the
public operation-failure vocabulary, not raw provider codes. Keep customer copy
neutral and retain the Payout ID and the `Request-Id` from the relevant request.

For a known or unknown failure code, do not automatically create another
Payout. Retrieve the operation, confirm the business intent and destination,
and use a new key only for a deliberately new Payout. An uncertain or lost HTTP
response is different: preserve the original key and follow
[Idempotency](/guides/idempotency).
