How to investigate a failed payment: a playbook for support teams

To investigate a failed payment, work in order. Find the payment by its reference, list every attempt, read the provider response on each attempt, check the 3-D Secure result, confirm the webhook reached your systems, then compare all that with what the customer saw. Most cases come down to an issuer decline, a blocked payment, failed or abandoned authentication, or a webhook that never arrived.

Topic
Product
Published
Updated
Reading time
10 min

In 30 seconds

  • Investigate in a fixed order: reference, attempts, provider response, 3-D Secure, webhook, customer view. Skipping steps leads to wrong answers.
  • A failed payment is not always a decline. It may have been blocked, abandoned or never sent, and each needs a different reply.
  • Trust the final server-side status, not the browser. Customers can leave the page, and result codes can change after they arrive.
  • 12 sources cited
Talk to us
On this page8 sections

A customer writes in: the payment failed, the money seems to have gone, and the order isn’t there. Support opens one dashboard, sees “declined”, tells the customer to call the bank, and the case comes back a day later. Often the answer was on the screen, one step further down.

This article is a playbook for that one payment. It sets out what to check, in order: the reference, the attempts, the provider response, the 3-D Secure result, the webhook and the customer’s view. It ends with a table of symptoms and likely causes. For trends across thousands of payments, use a decline dashboard instead; this article starts where that one stops, with a single case.

What do you need before you start?

Collect the facts first, so you search once and search well. You need:

  • Order or payment reference, from the confirmation email or the customer’s account.
  • Customer email and account ID.
  • Amount, currency and method. For cards, the last four digits only.
  • Date and time, with the customer’s time zone.
  • What they saw, in their own words or as a screenshot.
  • What the bank shows: pending, completed or nothing.

Never ask for a full card number or CVV. You don’t need either, and they should not appear in a ticket.

Then write down the question you are answering. “Why did it fail?” is different from “Did I pay?” and from “Where is my money?”. The steps below answer all three, but the reply to the customer depends on which one they asked.

How do you trace the payment and its attempts?

Step 1: find the payment. Search by your order reference first, then the provider’s payment ID. If you only have an email and amount, widen the time window for time zones. If nothing turns up, the customer may have stopped before a payment was created, or may have paid another merchant with a similar name.

Step 2: list every attempt. One payment can have many attempts. A customer may retry. A cascade may move the payment to another provider. Stripe’s model shows the structure: a PaymentIntent tracks the whole purchase, each try creates a Charge, and you need to list all charges to see the unsuccessful ones, because the object itself shows only the latest. The same logic applies at any provider.

For each attempt, note the provider, method, time, amount and result. Then read the pattern:

PatternWhat it usually means
One attempt, declinedIssuer or provider refused it; go to the provider response
Several attempts, last one approvedThe customer paid; a failed attempt may be what they saw
Several attempts, two approvedPossible duplicate; check captures and order records
Attempt with no final statusStill pending, timed out or abandoned
Attempts on different providersCascade or customer retry; read each response
No attempt at allFailed before a provider saw it

Note the final status separately, and use one you can trust. Stripe’s statuses show why: a payment waiting for authentication sits at requires_action, one that failed returns to requires_payment_method, and in its Dashboard all of these can appear as Incomplete. Adyen warns that its Pending and Received codes mean the final status isn’t available yet, and that you should not rely on the result code to update your order system, because the status can change after you receive it.

If the first attempt ended in a timeout, don’t assume it failed. Check the status before any retry. Stripe’s documentation explains that idempotency keys let you repeat a request safely after a connection error, without creating a second payment. Our article on webhooks and idempotency covers how that works.

How do you read the provider response?

Step 3: identify who said no. Stripe sorts failures into three types, and the split works across providers:

TypeWho refusedHow to recognise itWhat the customer should do
Issuer declineThe card issuerA decline code from the networkFix details, use another card or contact the bank
Blocked paymentYour or your provider’s fraud rulesNo issuer response; Stripe shows not_sent_to_networkNot a bank problem; your team decides
Invalid requestYour integrationAn error, often no payment on recordNothing; it is yours to fix

This is the step that saves the most time. If your own rule blocked the payment, sending the customer to the bank wastes a day for both of you. Stripe says that when it blocks a payment it doesn’t obtain authorisation from the issuer, and the outcome object shows the reason. Adyen separates these too: refusal reason 20, FRAUD, means pre-authorisation risk checks reached a score of 100 or more, while an issuer’s suspected fraud arrives as a different refusal.

For an issuer decline, record three things:

  • The raw network code, not only the provider’s label.
  • The Mastercard merchant advice code, if there is one. Our guide to merchant advice codes explains what each one tells you.
  • The provider’s own message, if it adds detail.

Expect little from generic codes. Stripe says issuers categorise most declines as generic, and discuss the specifics only with their cardholders. A do not honor tells you the issuer refused, and little else. Stripe lists the usual reasons as insufficient funds, incorrect card data and suspected fraud, and says that in the last case the customer must resolve it with their issuer. Our article on soft and hard declines covers which ones can be retried, and Visa’s rules forbid any reattempt after a Category 1 decline.

How do you check the 3-D Secure result?

Step 4: read the authentication outcome. If the card went through 3-D Secure, authentication has its own result, separate from authorisation. A payment can pass authentication and then be declined by the issuer, or fail authentication and never reach authorisation. Stripe’s flow shows both: after authentication it attempts the charge, and after a failure the payment returns to requires_payment_method, with no charge attempted.

The protocol reports a transaction status. Adyen’s reference lists the meanings:

StatusMeaningWhat to do next
YAuthenticatedRead the authorisation response
NNot authenticated; transaction deniedCustomer retries or uses another card; contacts the bank if it repeats
UAuthentication could not be performedCustomer tries again later or uses another method
AAttempted; proof of attemptRead the authorisation response
CChallenge requiredCheck whether the customer finished the challenge
RIssuer rejected the authenticationCustomer uses another card or contacts the bank

A reason code usually comes with it. Adyen lists examples such as 01, card authentication failed; 11, suspected fraud; 13, cardholder not enrolled; and 14, transaction timed out at the ACS, the issuer’s authentication server. Stripe reports a result such as authenticated, failed or attempt_acknowledged, with a result_reason such as abandoned, canceled, rejected or protocol_error.

Three patterns come up often:

  • Abandoned. The customer never finished, perhaps because the bank app didn’t open or they closed the page. Stripe shows an unfinished checkout at requires_action. Stripe’s mobile SDKs need a timeout of at least 5 minutes, so a stalled payment can stay open that long.
  • Failed. A wrong code or a rejected challenge. Adyen’s refusal 11, 3D Not Authenticated, means authentication didn’t run or didn’t succeed.
  • Authentication required. Adyen’s refusal 38 means the issuer refused an exemption and wants 3-D Secure, which is a reason to try again with authentication, not to tell the customer the card is bad. Our guide to 3-D Secure exemptions explains why this happens.

Adyen’s refusal 42 points to a problem at the network or issuer. If many customers of one bank hit it at once, escalate to your provider rather than handling each ticket alone.

How do you check the webhook?

Step 5: confirm your systems got the final status. A provider can show a paid payment while your shop shows nothing, because the webhook that should update the order never arrived or wasn’t processed. This is the classic cause of “I paid but have no order”.

Check four things:

  1. Was an event sent? Look at the delivery log. Stripe lists events as delivered, pending or failed, with the HTTP status of each attempt.
  2. Did delivery succeed? Stripe’s table of errors covers connection failures, redirects, 4xx, 5xx, TLS errors and timeouts. Adyen says a 401 usually means your server refused the connection because of invalid credentials.
  3. Is a retry still coming? Stripe retries for up to three days in live mode, and Adyen retries on a schedule from 30 seconds up to 8 hours, then from a queue for up to 30 days. The order may fix itself, but a customer who is waiting needs an answer now.
  4. Was it processed? A 200 response only means the event was received. Check your order system’s logs. Stripe doesn’t guarantee delivery order, and an endpoint can receive the same event twice, so a handler can skip or mishandle an event if it isn’t built for this.

If the provider has a final status that your order system lacks, fix the order from the provider’s record and resend the event. Stripe warns against fulfilling orders from the browser, because customers can leave the page after paying. The same logic applies to investigations: the redirect back to your site proves nothing, either way.

What did the customer actually see?

Step 6: compare your record with the customer’s view. Most confusion comes from the gap between them.

  • Bank app shows a pending amount. This may be an authorisation hold, not a charge. Stripe says that even for a blocked payment, customers with some card types might see the issuer’s authorisation, and that the issuer typically removes it within a few days. Timing is up to the issuer, so don’t promise a date.
  • Bank shows a completed charge. If your records agree, the payment succeeded and the problem is on the order side. If yours show nothing, ask for a statement screenshot and check the merchant name and amount. It may be another merchant.
  • Customer saw an error, but a later attempt worked. They may believe they paid twice, or not at all. Show them the attempts in plain words.
  • Screen said failed, but provider says approved. This points to a timeout or a dropped redirect, so go back to the webhook step.
  • Customer’s bank wants to trace it. For a settled card transaction, the acquirer can supply the acquirer reference number, a 23-digit reference that Stripe says stays with the transaction across the network and that bank staff use to trace it.

Then write the reply. Say what happened, what they should do next and what you have done. Keep it specific: “Your bank declined the payment, and no money was taken. Please try another card, or contact your bank and quote the date and amount” beats “Your payment failed”. Don’t repeat a raw fraud code to the customer. Say the bank refused the payment and ask them to contact it.

Which symptom points to which cause?

Use this as a quick guide, then confirm it with the steps above.

SymptomLikely causeFirst checkWho acts
“Card declined”, no detailGeneric issuer declineNetwork code, advice codeCustomer and bank
Declined straight away, no bank alertBlocked by fraud rulesBlock reason in the attemptYour risk team
Payment form gives an error, no payment on recordInvalid request or integration errorProvider logsYour developers
Stuck on the bank’s pageAbandoned or timed-out authentication3-D Secure result and reasonCustomer retries
Failed after entering a codeAuthentication failedStatus N or RCustomer and bank
Paid, but no orderWebhook failed or not processedDelivery log and order logsYour developers
Money pending, order failedAuthorisation holdAttempt status, any reversalIssuer releases it
Charged twiceDuplicate attempts, or a hold plus a chargeAll attempts and capturesYour payments team
Method pending for a long timeDelayed confirmation on a local methodProvider statusWait, then escalate
Many customers, one bankIssuer or network problemGroup by BIN, then escalateYour provider
Many customers, one providerProvider incidentProvider status pageYour payments team
Small repeated failures, odd namesCard testingAttempts by BIN and IPYour risk team

When a symptom appears more than a few times a week, stop treating it as a ticket. Add it to your decline dashboard and fix the cause.

How does Omno help investigate a failed payment?

Omno keeps the whole story of a payment in one place. The transaction trail on the reporting and analytics page shows every attempt, cascade step, provider response and webhook, alongside a customer profile, so support can follow one payment across providers without opening each dashboard. Role-based access lets support see what it needs, and custom decline messages tell customers what to do next.

Key facts

  • Stripe sorts failed payments into three types: issuer declines, blocked payments and invalid API calls (Stripe docs, 2026).
  • Stripe says issuers categorise most declines as generic, and discuss the specifics only with their cardholders (Stripe docs, 2026).
  • Stripe says that for some card types, a customer may see an authorisation for a blocked payment, which the issuer typically removes within a few days (Stripe docs, 2026).
  • Stripe retries webhook delivery for up to three days in live mode, and doesn't guarantee events arrive in order (Stripe docs, 2026).
  • Adyen retries failed webhooks on a schedule, then keeps retrying from a queue for up to 30 days (Adyen docs, 2026).
  • Stripe's mobile SDKs require a 3-D Secure timeout of at least 5 minutes, covering network time and customer input (Stripe docs, 2026).

Changelog

  • First published.

Frequently asked questions

The customer says money left their account but the payment failed. What happened?

Usually this is a temporary authorisation hold, not a completed charge. Stripe says that for some card types, customers might see the issuer's authorisation on their statement even when the payment was blocked, and that the issuer typically removes it within a few days. If your records show a successful capture, it is a real charge, and the question becomes why your order system missed it.

Can I ask the bank why a payment was declined?

Usually not. Stripe's documentation says that for privacy and security reasons, issuers discuss the specifics of a decline only with their cardholders. You can tell the customer the type of decline, and ask them to contact their bank with the date, amount and merchant name.

How do I find a payment if the customer has no order number?

Search by email, the last four card digits, amount and approximate time, with a window wide enough for time zone differences. If nothing appears, the customer may have failed before a payment was created, for example at a blocked step, or may have paid a different merchant with a similar name.

Should support staff retry a failed payment for the customer?

No. Ask the customer to try again with the same or another method. Retrying a hard decline breaks scheme rules, and Visa's rules forbid any reattempt after a Category 1 decline. If the outcome is unknown, check the final status first, so you don't create a second charge.

How long should we keep payment logs for support?

Long enough to cover late complaints. Check how far back your provider's dashboards go, and keep your own record of the payment reference, attempts and final status. Stripe, for example, can resend events from its Dashboard for up to 15 days after creation and through its command-line tool for up to 30 days.

esc
↑↓ to move ↵ to open All results