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

# My Order Was Rejected — Is It Me, My Setup, or the Payment Method?

> A decision tree for the rejections merchants raise most: A0018 payment-method/contract mismatch and every dimension that produces it, A0001 after a key rotation, C0005 channel rejection and the failure reason returned with it, A0017 on refunds, and how to tell a not-yet-enabled payment method apart from a bad parameter.

Three rejections account for most go-live tickets: `A0018`, `A0001` and `C0005`. They look alike —
a code, a short message, no detail — but they need completely different responses. This page is the
decision tree. Per-code reference is the published
[Error code list](/docs/en/developer-docs/tools-and-references/developer-tools/error-codes); the
mechanics of each code are in
[Common Errors Troubleshooting](/docs/en/support/errors-troubleshooting-guide) and
[Limits, Currency & Configuration Errors](/docs/en/support/error-codes-and-limits-supplement).

## Which of these am I looking at?

| Code | One-line reading | Whose problem |
| - | - | - |
| `A0001` | The API key was not accepted | Your credentials or your environment |
| `A0002` | The signature did not verify | Your signing |
| `A0003` | The request itself is malformed | Your payload |
| `A0018` | No agreement of yours matched this whole request | Your setup — or a parameter that narrowed too far |
| `A0008` / `A0020` / `A0021` | The amount or the daily total is outside a limit | Your request against your limits |
| `A0035` / `A0036` | Manual capture is not available, or not now | Your setup or the order's state |
| `C0005` | The payment method refused the payment | The payment method — read the failure reason |
| `C0007` | The payment method is unavailable right now | Temporary; retry or offer another method |
| `E0001` | The outcome is not yet known | Nobody's yet — keep querying |

The first letter is the fastest triage there is: `A` is yours to fix, `C` is on the Waffo or
payment-method side, `E` means undetermined. Never treat an `E` as a failure — the rule and the
retry pattern are in the published
[Error handling](/docs/en/developer-docs/core-concepts/error-handling).

## Is `A0018` "not enabled yet", or did I send something wrong?

Both are possible, and this is the crux of the question. `A0018` does not mean "the payment method
you named is not signed". It means **nothing you are contracted for survived the whole request**,
and the request narrows the candidates on many dimensions at once. Any one of them can empty the
set, and they all come back as the same code and the same message.

Work through them in this order — the first mismatch you find is your answer:

| # | Dimension | Check |
| - | - | - |
| 1 | **Merchant ID** | Does the merchant ID in the body belong to the API key you signed with? A mismatch here makes everything below moot |
| 2 | **Payment method and type** | Are `payMethodName` / `payMethodType` exactly as they appear on Service → Payin — or omitted entirely? |
| 3 | **Order currency** | Is there a row carrying this `orderCurrency` for that method? Matched exactly |
| 4 | **User currency** | If you pinned `userCurrency`, is that pair on a row? Omitting it removes this dimension |
| 5 | **Agreement status and validity window** | Is the row `Active`, and is today inside its validity dates? A row that has ended does not appear at all in the inquiry response |
| 6 | **Country** | If you pinned `payMethodCountry`, does it match the row's payment-method country? Globally available methods do not belong to a country — do not pin one for them |
| 7 | **Terminal** | Is the `userTerminal` you sent one the method supports? |
| 8 | **Conditionally required fields** | Some methods require extra fields; missing one empties the set rather than producing a field error — see [Conditional & Required Fields](/docs/en/support/conditional-required-fields-faq) |
| 9 | **Card or token data** | Sending raw card data or a saved token restricts candidates to card-class agreements, and a token must still resolve to a method you are contracted for |
| 10 | **Cross-currency pricing** | A cross-currency order that cannot be priced is rejected here too |
| 11 | **Real-time availability** | The method may be contracted but unavailable at that moment |

So: **not-enabled and sent-wrong are distinguished by elimination, not by the code.** The fastest
way to separate them:

1. Call `/api/v1/paymethodconfig/inquiry`. If the method, country and currency combination is not in
   the response, it is a setup question — nothing you change in the payload will help.
2. If it *is* in the response with an availability of "available", the combination is contracted and
   the rejection came from something the request itself added — one of rows 1, 6, 7, 8, 9 above.
   Remove the optional narrowing parameters one at a time and retry.

Two codes sit next to `A0018` and mean the opposite of a missing contract — they mean you have
**more** than one match and must be specific: `A0022` (name the product) and `A0033` (name the
payment-method country).

## Why isn't an unsupported currency its own error code?

Because the currency is one of the dimensions above, not a separate check. An order currency or a
currency pair you are not contracted for comes back as `A0018`, with the payment-method wording. Do
not wait for a currency-specific code — see
[Do I have to enable a currency before I can use it?](/docs/en/support/currency-and-method-enablement-faq).

## The same code appeared on a subscription. Does it mean the same thing?

The code is shared but the reading differs. On the acquiring side it is the contract mismatch above.
On the **subscription** side it means there is no usable payment method left to charge that
subscriber with — for example the saved method has been removed. The published code list glosses it
the second way; the message text you receive is the contract wording. Read it together with the API
you called.

One consequence worth building for: on a renewal after the first period, this code is treated as
**not retryable** — the schedule will not keep trying it. Fix the payment method rather than waiting
for a retry. See
[Subscription retries & payment methods](/docs/en/support/subscription-retry-and-payment-methods-faq).

## I rotated my keys and now I get `A0001`. Is the new key broken?

Usually not. Three things to rule out, in order:

| Check | Detail |
| - | - |
| **Environment** | Sandbox and production have separate keys **and** separate domains. A sandbox key sent to the production domain is an `A0001`, and vice versa |
| **Activation state** | A submitted key is not usable until it is active. A submission still under review, or one that was rejected, behaves like a key that does not exist |
| **Propagation** | A key that has just become active is not accepted the same instant everywhere. Do a rotation as an overlap — add the new key, wait, keep the old one in place until the new one has verified real traffic — rather than as a cutover |

How long that window is, the exact order in which the key, its scope, the signature and your IP
allowlist are checked, and how `A0001` differs from `A0002` and from a scope refusal, are in
[API Credential Scope & Auth Error Triage](/docs/en/support/api-credential-scope-and-triage-faq). The
submission and rotation procedure, and where to see why a submission was rejected, are in
[Production API Keys & Public Keys](/docs/en/support/production-api-key-and-public-key-faq).

If the key is accepted but the call is refused anyway, the cause is usually what that key is
permitted to do — a different rejection, not `A0001`.

## What does `C0005` actually tell me, and where is the reason?

`C0005` — *Payment channel rejection* — means the payment method refused the payment. On its own it
tells you almost nothing, because it is the code a wide range of underlying refusals map to,
including every card decline.

The detail is in the **failure reason returned with the order**, which has two halves:

| Field | Use |
| - | - |
| `orderFailedCode` | A stable value to branch on in your own code |
| `orderFailedDescription` | Human-readable text for support conversations and logs |

They arrive together as `orderFailedReason` on
[Order inquiry](/docs/api-reference/introduction), and the Portal shows the same pair on the transaction
record as *Order Failure Code* and *Order Failure Description* — see
[Transaction Field Reference](/docs/en/support/transaction-field-reference-faq).

So the routine is: **never branch on `C0005`; branch on the failure code inside it.** Descriptions
such as an authentication step that could not be started, or a card refused by the issuing bank on
fraud or on legal grounds, are exactly the sort of thing that arrives this way, and they call for
very different handling.

## Which `C0005` failures are worth retrying?

Retryability belongs to the underlying reason, not to `C0005`. The classification and what to do
about each class — including which declines must never be retried and which need the customer to
re-enter their credential — is in
[A card was declined. Should I retry?](/docs/en/support/order-amount-precision-and-decline-faq).

Two rules on top of that:

* **Show the customer a usable message and offer another payment method.** Waffo checks exactly this
  behaviour during integration acceptance for channel rejections and system-unavailable responses —
  see the published
  [Acceptance criteria](/docs/en/developer-docs/tools-and-references/references/acceptance-criteria).
* In the sandbox, several reserved amounts return `C0005` on purpose so you can build that path. If
  you get `C0005` on an amount you did not expect to be special, check the reserved list before
  concluding anything — see
  [Sandbox simulator](/docs/en/developer-docs/tools-and-references/developer-tools/sandbox-simulator).

## A refund came back `A0017`. Can that order ever be refunded by API?

`A0017` — *the order cannot be refunded because the payment channel does not support it* — comes
from the payment method itself, and it is **not retryable**. Sending it again unchanged produces the
same answer.

Before treating it as final, separate it from the other refund rejections:

| Situation | Where to look |
| - | - |
| The method permits no refunds at all, or only a shape you did not ask for | The refund policy on your agreement — `refundAllowed` on the inquiry response, `Refundable` on Service → Payin |
| The refund window has closed | The refund period on the same row |
| The order is not in a refundable state, or is already fully refunded | The order itself |
| The method cannot process a refund through the API | `A0017` |

All four, and what to do in each case, are in
[Payment Method Refunds & Limits](/docs/en/support/payment-method-refund-limits-faq) and
[Refund FAQ](/docs/en/support/refund-faq).

## Where do I look next?

| Question | Page |
| - | - |
| What are my limits, and which limit did I hit? | [Payin Agreements & Transaction Limits](/docs/en/support/payin-agreements-and-limits-faq) |
| What is contracted for me, from code? | [Payment Method Configuration & Limits](/docs/en/support/payment-method-config-and-limits-faq) |
| Is this a currency problem? | [Currency & Method Enablement](/docs/en/support/currency-and-method-enablement-faq) |
| Is this mine to fix at all? | [What can I change myself?](/docs/en/support/self-service-boundaries-faq) |
| Signature, idempotency and unknown-status handling | [Common Errors Troubleshooting](/docs/en/support/errors-troubleshooting-guide) |


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