Building a decline dashboard: data, code groups and alerts

A decline dashboard starts with one record per payment attempt: the raw network response code, the provider's own code, the Mastercard merchant advice code, the 3-D Secure result, BIN, issuer and issuing country, provider, method, amount and whether it was a retry. Codes from every provider are mapped into a few decline groups, viewed over time, by country, provider and BIN, on intents and attempts, with alerts against your own baseline.

Topic
Approval rate
Published
Reading time
8 min

In 30 seconds

  • Store the raw network code, the provider's code and the Mastercard advice code for every attempt; the provider's label alone is not enough.
  • Map every provider's codes into a small set of decline groups, each with one default action, and review the mapping as codes change.
  • Report on payment intents and on attempts side by side, and alert on changes against your own baseline rather than on industry averages.
  • 9 sources cited
Talk to us
On this page8 sections

Every payment provider has a decline report. The trouble starts when there are two or three of them. One calls a decline “Refused”, another “do_not_honor”, a third “20005”. One counts a cascaded payment twice, another once. The monthly approval rate falls by two points and nobody can say whether it was one issuer, one country, one provider or a change in your own fraud rules.

This article explains how to build a decline dashboard that answers those questions: the data to capture for every attempt, how to normalise codes across providers, the views a payments team needs, where to set alerts and how to run a weekly review. It builds on our guides to calculating approval rate and soft and hard declines.

What data should you capture for every attempt?

One row per authorization attempt, linked to the payment intent it belongs to. If a field is not captured at the time, it cannot be recovered later.

FieldWhy it matters
Intent ID, attempt ID, attempt numberSeparates purchases from retries and cascades
Retry or cascade flag, and what triggered itShows which rules created extra attempts
Provider and acquirerCompares routes on the same traffic
Method, scheme, card typeDebit, credit and prepaid behave differently
BIN, issuer, issuing countryFinds issuer and cross-border patterns
Amount and currencyLimits and funds declines depend on them
3-D Secure resultSeparates authentication failures from issuer declines
Raw network response codeWhat the issuer actually sent
Provider’s own code and messageWhat your provider calls it
Mastercard merchant advice codeThe issuer’s instruction for the next attempt
Where it failedYour fraud rules, the provider’s risk checks, or the issuer

Two fields are often missing. The raw code is not always passed through: Adyen, for example, returns it only once the merchant turns on the raw acquirer result setting, and its numeric refusalCodeRaw exists only for Visa and Mastercard payments on Adyen’s own acquiring. And the merchant advice code is dropped by many internal mappings. Our article on merchant advice codes explains why it should be kept.

The “where it failed” field matters as much as the code. Stripe separates issuer declines from blocked payments and invalid API calls, and a blocked payment shows a network status of not_sent_to_network. Checkout.com uses a separate 4xxxx range for risk responses. If your own blocks and issuer declines share one column, our article on false declines shows how that hides the problem.

How do you normalise codes across providers?

Map every code from every provider into a small set of groups, each with one default action. The raw network code is the anchor, because it is the same whichever provider carried the payment; the provider’s code is the fallback.

GroupVisa / Mastercard raw codesStripe codeAdyen reasonDefault action
Generic05do_not_honor, generic_declineRefusedOne retry on another route or with 3-D Secure
Funds and limits51, 61, 65 (Visa)insufficient_funds, card_velocity_exceededNot enough balance, Withdrawal amount exceededRetry later or offer another method
Authentication1A (Visa), 65 Identity Check (Mastercard)authentication_requiredAuthentication requiredRetry with 3-D Secure
Card data54, N7, 14expired_card, incorrect_cvc, incorrect_numberExpired Card, CVC Declined, Invalid Card NumberAsk the customer to correct
Issuer fraud59 (Visa), 83 (Mastercard)Read the network codeIssuer Suspected FraudDo not cascade; review
Card blocked04, 07, 41, 43, R0, R1, R3lost_card, stolen_card, pickup_cardBlocked Card, Revocation Of AuthStop; never retry
Technical91, 96issuer_not_available, processing_error, reenter_transactionIssuer Unavailable, Acquirer ErrorFail over or retry shortly
Not sent to issuernoneblocked outcomeFRAUD (Adyen risk)Review your own and provider rules

The code meanings come from Stripe’s lists of network and decline codes and Adyen’s refusal reasons. Checkout.com’s codes fit the same groups: 20005 do not honour, 20051 insufficient funds, 20059 suspected fraud, 20154 3DS authentication required and 30004 pick up card. Checkout.com also publishes which of its codes fall into each of Visa’s four response code categories, which is a useful check on your own mapping.

Three rules keep the mapping honest. Keep an “unmapped” group and review it weekly, because new codes appear. For Mastercard, let the advice code override the group’s default action. And version the mapping, since Adyen notes that schemes and issuers sometimes change the raw text without notice.

Which views does a payments team need?

Six views cover most questions. Each should be filterable by method, scheme, country and period.

ViewShowsQuestion it answers
Declines by group over timeDaily share of attempts in each groupDid something change, and what kind of decline is it?
By issuing countryApproval and group mix per card countryIs a cross-border or domestic problem growing?
By provider, same segmentGroups per provider for the same country and methodIs one route worse on the same traffic?
By BIN and issuerTop BINs by declined volume and generic shareIs one issuer refusing us in particular?
Intent versus attemptBoth rates on one chartAre retries hiding or causing the change?
Retries and cascadesRecovery by group and advice codeWhich retry rules earn their attempts?

The intent versus attempt view is the one most teams lack. Stripe’s acceptance analytics show the gap: its raw rate counts every attempt, while its deduplicated rate groups retries of the same purchase and takes the final outcome. In Stripe’s own example, one purchase approved on the third attempt is a 33.3% raw rate and a 100% deduplicated rate. Checkout.com reports first attempt authorization success and the uplift from retries for the same reason.

Decide also what the denominator includes. Stripe’s authorization rate leaves out invalid API calls, failed 3-D Secure and blocked payments, because those fail before the issuer is asked; its payment success rate includes them. Show both, and label which one each chart uses.

For the BIN view, Checkout.com describes the issuing BIN as the first six to eight digits of the card number. Our article on BIN routing covers what to do once the view points to a single issuer.

Where should you set alerts?

On changes against your own baseline, not on industry averages. Decline rates depend on countries, card mix and customers, so a figure that is normal for one merchant is an incident for another.

  • Technical group. Alert within the hour when the share of technical declines at one provider rises well above its median for the same hour of the week. This is usually an outage or a connection problem.
  • Generic group by issuing country. Alert daily when one country’s generic share moves sharply against its four-week average.
  • Unmapped codes. Alert when any new code appears more than a handful of times.
  • Stop advice retried. Alert on any retry after MAC 03 or 21, or after a card blocked code.
  • Volume. Alert on a sudden rise in attempts with a falling approval rate. Stripe notes that card testing can show as a lower rate and a spike in payment count.

Set each threshold as a setting, start loose, and tighten it once you know which alerts lead to action.

What does the weekly review look like?

Thirty minutes, the same agenda every week, with payments, risk and an engineer present.

  1. Intent-level approval against the previous four weeks, by top countries and methods.
  2. Group mix. Which decline group moved, and at which provider.
  3. Top ten BINs by declined volume. New entries and generic-share changes.
  4. Unmapped and new codes. Add each to the mapping or open a question with the provider.
  5. Retry and cascade recovery by group. Remove rules that recover almost nothing.
  6. Actions and owners. One line each, checked again next week.

Worked example: a weekly review at an electronics store

Example figures, for illustration only.

An online electronics store routes cards through two providers. This week it had 20,000 payment intents and 23,000 attempts, including retries and cascades. 16,400 intents were approved: an intent-level rate of 82.0% and an attempt-level rate of 16,400 ÷ 23,000 = 71.3%. The 6,600 declined attempts break down as follows.

Decline groupFour-week weekly averageThis weekChange
Generic2,3502,400+50
Funds and limits1,4801,500+20
Authentication620600-20
Card data510500-10
Issuer fraud290300+10
Card blocked410400-10
Technical310900+590
Total5,9706,600+630

Only the technical group moved. Drilling into it by provider shows 780 of the 900 at provider B, in one three-hour window on Tuesday, which the hourly alert had already flagged. Cascading sent 700 of those payments to provider A, which approved 560. That is why the intent-level rate barely moved while the attempt-level rate fell: the customers mostly got through, at the cost of extra attempts.

The actions: ask provider B for an incident report, and check why 80 of its technical failures were not cascaded. Without the provider split and the intent versus attempt view, the team would have seen a lower attempt rate and started tuning fraud rules.

What are the common mistakes?

  • Keeping only the provider’s label. Two providers can call the same issuer response by different names. Without the raw code, the comparison is unreliable.
  • Mixing your blocks with issuer declines. Your own fraud rules and the provider’s risk checks need their own group, or a rule change looks like an issuer problem.
  • One rate for everything. Attempt-level and intent-level numbers answer different questions; show both and say which a chart uses.
  • Alerting on averages from elsewhere. Thresholds borrowed from another business fire too often or never. Use your own baseline.
  • Letting the mapping go stale. New codes and changed texts pile up in “other” unless someone reviews them weekly.
  • No owner for actions. A review that ends without names and dates is a meeting, not a routine.

How does Omno help build a decline dashboard?

Omno’s dashboard shows approval and decline reasons by provider, method, country and customer group, with real-time success metrics, and the routing-decision log records the eligible providers, the chosen one and every cascade attempt with its result for each payment. Because every connected provider reports through one data model, the views can compare routes on the same traffic. For custom views, such as BIN-level groups or your own code mapping, data export can feed your warehouse. The reporting and analytics page lists what is included.

Key facts

  • Stripe says many card payments are categorised as generic declines, the most common being do_not_honor, and that issuers discuss specifics only with their cardholders (Stripe docs, 2026).
  • Stripe's raw rate counts every attempt, while its deduplicated rate groups retries and uses the final outcome: one purchase approved on the third attempt is 33.3% raw and 100% deduplicated (Stripe docs, 2026).
  • Stripe's authorization rate leaves invalid API calls, failed 3-D Secure and blocked payments out of the denominator, because those fail before the issuer is asked (Stripe docs, 2026).
  • Checkout.com groups its response codes by range: 10xxx approved, 20xxx soft decline, 30xxx hard decline and 4xxxx risk responses (Checkout.com docs).
  • Adyen returns a numeric raw code only for Visa and Mastercard payments on its own acquiring, and warns that schemes and issuers sometimes change the raw text without notice (Adyen docs, 2026).
  • Checkout.com reports first attempt authorization success and the uplift from retries separately, with declines by issuing country, bank and BIN (Checkout.com docs).

Changelog

  • First published.

Frequently asked questions

Should the dashboard use the raw network code or the provider's decline code?

Both, in different places. The provider's code is stable and readable, so it suits customer messages and quick filters. The raw network code is what the issuer actually sent, and it is the only way to compare providers that translate codes differently. Group on the raw code where you have it, and fall back to the provider's code where the provider does not pass the raw value on.

What decline rate should trigger an alert?

There is no universal figure, because decline rates depend on the merchant's countries, methods, card mix and customers. Set thresholds against your own baseline for the same segment and time of day, for example a share of technical declines well above its recent median, and tune them after the first few weeks so the alerts that fire are worth reading.

Should a payments team look at intent-level or attempt-level numbers?

Both, kept apart. Intent-level numbers count each customer purchase once and tell you how many customers got through. Attempt-level numbers count every authorization and tell you how each provider and route performs. Stripe calls these deduplicated and raw rates; Checkout.com reports first attempt success and the uplift from retries. A change that moves one and not the other is itself a finding.

How should local payment method failures be grouped?

Separately from cards. Stripe's documentation notes that, unlike card issuer declines, the reasons and codes for local payment method failures vary by method. Keep a group set per method family, such as bank transfers, wallets and vouchers, and add expiry and abandonment as their own groups, since an unpaid voucher is not a decline.

esc
↑↓ to move ↵ to open All results