Skip to main content
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; the mechanics of each code are in Common Errors Troubleshooting and Limits, Currency & Configuration Errors.

Which of these am I looking at?

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.

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: 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?.

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.

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

Usually not. Three things to rule out, in order: 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. The submission and rotation procedure, and where to see why a submission was rejected, are in Production API Keys & Public Keys. 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: They arrive together as orderFailedReason on Order inquiry, and the Portal shows the same pair on the transaction record as Order Failure Code and Order Failure Description — see Transaction Field Reference. 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?. 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.
  • 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.

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: All four, and what to do in each case, are in Payment Method Refunds & Limits and Refund FAQ.

Where do I look next?