Dashboard payment KPI
TL; DR
One dashboard - three layers: Funnel health (Attempt→Auth→Capture), Financial efficiency (TtW/TtR, Cost/GGR, FX) and Infrastructure reliability (Webhook/Latency/Settlement). The secret is correct calculation bases, mandatory segmentation (country × provider × method × BIN × ticket _ size × risk), threshold SLOs and ready-made playbooks when leaving the corridors.
1) For whom and what questions we close
CEO/GM (daily, 3-5 min): "Payment conversion and withdrawal speed are normal? Is the cost of accepting money under control?"
Head of Payments/Treasury (every hour): "Where is the degradation by provider/country/method? Is there enough liquidity for instant payments?"
Fraud/Risk (daily): "AR with anti-fraud? Abandon на 3DS и Soft declines?»
Support/Operations (online): "What is the ETA for withdrawal and return? Where are the webhooks hanging?"
Finance/Recon (D + 1): "Settlement on time? Commissions and FX fit the plan?"
2) Main metrics and exact definitions
2. 1 Payment funnel
Attempt - initiated payments.
Auth Approved - approved authorizations.
Captured - successfully written off.
- `AR_gross = Auth_Approved / Auth_Attempted`
- `AR_net = Captured_Tx / Auth_Attempted`
- `Capture_Success = Captured_Tx / Capture_Attempted_Tx`
- `Capture_Latency_p95 = p95(capture_ts - auth_ts)`
2. 2 Outputs and returns
Payout Success % = Success_Payouts / Attempted_Payouts
TtW p95 = p95(payout_credited_at - payout_initiated_at)
Refund Rate = Refunded_Tx / Captured_Tx
TtR p95 = p95(refund_credit_at - refund_initiated_at)
Refund Error % = Refund_Failed / Refund_Attempted
Refund_to_Source% - proportion of returns to the original method
2. 3 Cost and FX
Cost/Tx = Fee_fixed + AmountFee_pct + FX_Spread
Cost/GGR = ΣCost / GGR
FX Slippage (bps) = (exec_px − mid_px)/mid_px × 10 000
2. 4 Reliability of integrations
Webhook Delivery p95 (сек), Success %
API Latency p95/p99 (auth/capture/refund/payout)
Settlement Timeliness = Batches that came to the declared T + N/all Batches for the period
2. 5 3DS/friction (for cards)
3DS Challenge Share = Challenge / 3DS_Total
Frictionless Share = Frictionless / 3DS_Total
Abandon on 3DS = 3DS_Started − 3DS_Completed
3) Sections and filters (minimum set)
Фильтры в шапке: `date range (UTC)`, `country`, `provider`, `method_group`, `BIN`, `device/os`, `ticket_size bucket (≤€50 / €50–200 / >€200)`, `risk_segment`, `kyc_tier`, `new_vs_returning`, `affiliate`.
Mandatory sections in charts/tables:- country×provider, BIN×country, method×provider, device/os, ticket_size.
4) Layout of the main screen
1. Upper KPI plate (for yesterday/today, comparison to p7 median):
`AR_net`, `Capture_Success`, `Payout Success%`, `TtW p95`, `TtR p95`, `Cost/GGR`, `Webhook p95`, `Settlement Timeliness`.
2. Funnel (Attempt→Auth→Capture) with segment selection and display of failure causes (ISO top codes/on rails).
3. Heatmap AR by 'country × provider' and a separate BIN heatmap for the top volume.
4. 3DS panel: Challenge/Frictionless/Abandon + comparison to the bench line.
5. Payout & Refund Health: Success%, p95 (TtW/TtR), ошибки, Refund_to_Source %.
6. Cost & FX: Cost/GGR by method, FX slippage/fees by site.
7. Integration reliability: Webhook delivery p95/Success%, API latency p95/p99, Duplicate rate, Report delivery SLA.
8. Incident panel: active alerts (see § 8), status of feilovers and treasury notes (leftovers L0, prefund).
5) SLO and alerts (corridors)
Benchmarks (portfolio/markets calibrated):- 'AR _ gross' 3DS2 cards: 82-92% (by segment); 'AR _ net' ≥ 80%
- `Capture_Success` ≥ 98. 5% (hourly)
- `Webhook p95` ≤ 3 с, Success ≥ 99. 9%
- `Payout TtW p95` instant ≤ 120 с; (T + 1) - 100% on day D + 1
- 'Refund TtR p95'cards ≤ T + 1 bp; instant ≤ 60 с
- `Refund Error %` < 0. 3%
- `Settlement Timeliness` ≥ 99%
- 'Cost/GGR '- individual target corridor according to the method
- 'AR_gross↓> 3 pp' to 7-day median (country/PSP/BIN) → P1/P0
- `Capture_Success < 98%` (час) → P1
- 'Webhook p95> 5 c'or duplicates> 0 → P1
- `Payout TtW p95 > SLO` или Success%<99% → P1
- `Refund Error% > 0. 3%` или `Double Refund > 0` → P0
- `Settlement on-time < 99%` → P1
- 'Cost/GGR'out of corridor using P2 → method
Each alert opens the runbook'a card (actions/escalation/feilover).
6) Formulas and calculation bases (detailing)
All shares - with an explicit base: indicate 'denominator' in the type.
Times - in UTC; p-quantiles: PERCENTILE_CONT.
'AR_clean' (operational) = 'Auth_Approved / (Auth_Attempted − Fraud_Preblocked − Abandon_3DS)'
`Net_Conversion` = `Captured_Tx / Auth_Attempted_Tx`
`Refund_to_Source %` = `Refund_to_Original_Method / Total_Refunds`
'Idle Cash% '(in treasury mini widget) =' (Balance − Target_Balance )/Balance'
7) UX patterns
Above is a KPI plate, below is funnel + heatmaps, below is integration and finance.
Tultips with formula/base/exceptions (for example, "after antifraud").
Comparative line: p7 median and "yesterday "/" last Monday. "
Drill-down by click: from heatmap to fault BIN→Issuer→kody table.
Snapshots for RCA: Button "pin" current view for post-mortem.
8) Playbooks (built-in action cards)
Auth drop → switch smart-routing, raise 3DS-challenge to BIN, limit retrays.
Webhook delays → enable polling, freeze auto-refands/dangerous auto-payments, increase idempotence.
Payout degradation → rail feiler, treasury top-up, VIP prioritization.
Settlement delay → StressRes, mark "Suspense," escalation in PSP.
Refund errors/duplicates → refund-freeze, reconciliation, reversal of duplicates.
(The card contains a checklist and escalation contacts.)
9) Data model (minimum sufficient)
events/payments_flat:
payment_id, user_id, country, provider, method_code, action(deposit/refund/payout),
attempt_ts, auth_status, auth_ts, three_ds(flow, challenge_flag, started_ts, completed_ts),
capture_status, capture_amount, capture_ts, partial_flag,
refund_status, refund_amount, refund_initiated_ts, refund_credit_ts,
payout_status, payout_amount, payout_initiated_ts, payout_credited_ts,
fees_fixed, fees_pct, fx_spread, currency, amount,
risk_segment, kyc_tier, bin, asn, device_os, ticket_bucket
events/webhooks:
provider, event_kind, event_ts, delivered_ts, retries, duplicate_flag, idempotency_key
settlements/reports:
provider, batch_id, settlement_date, amount_settled, currency, fee_amount, status
treasury/pockets (mini-widget):
pocket_id, counterparty, currency, balance, target_balance, low_watermark, updated_at
Indexes: by 'provider', 'method _ code', 'country', 'bin', 'event _ ts'.
10) SQL slices (example)
10. 1 Funnel and AR
sql
WITH base AS (
SELECT
DATE_TRUNC('hour', attempt_ts) AS h,
country, provider, method_code,
COUNT() FILTER (WHERE auth_status='ATTEMPTED') AS auth_attempted,
COUNT() FILTER (WHERE auth_status='APPROVED') AS auth_approved,
COUNT() FILTER (WHERE capture_status='CAPTURED') AS captured_tx
FROM payments_flat
WHERE action='deposit'
GROUP BY 1,2,3,4
)
SELECT h, country, provider, method_code,
auth_approved::decimal / NULLIF(auth_attempted,0) AS ar_gross,
captured_tx::decimal / NULLIF(auth_attempted,0) AS ar_net
FROM base;
10. 2 Webhook SLA
sql
SELECT
DATE_TRUNC('hour', event_ts) AS h, provider,
PERCENTILE_CONT(0. 95) WITHIN GROUP (ORDER BY EXTRACT(EPOCH FROM (delivered_ts - event_ts))) AS wb_p95_sec,
AVG(CASE WHEN retries=0 AND NOT duplicate_flag THEN 1 ELSE 0 END) AS wb_success
FROM webhooks
GROUP BY 1,2;
10. 3 Refund & Payout Health
sql
SELECT
DATE_TRUNC('day', COALESCE(refund_initiated_ts, payout_initiated_ts)) d,
method_code, provider,
COUNT() FILTER (WHERE refund_status='ATTEMPTED') AS refund_attempted,
COUNT() FILTER (WHERE refund_status='SUCCESS') AS refund_success,
PERCENTILE_CONT(0. 95) WITHIN GROUP (ORDER BY EXTRACT(EPOCH FROM (refund_credit_ts - refund_initiated_ts))) AS ttr_p95_sec,
COUNT() FILTER (WHERE payout_status='ATTEMPTED') AS payout_attempted,
COUNT() FILTER (WHERE payout_status='SUCCESS') AS payout_success,
PERCENTILE_CONT(0. 95) WITHIN GROUP (ORDER BY EXTRACT(EPOCH FROM (payout_credited_ts - payout_initiated_ts))) AS ttw_p95_sec
FROM payments_flat
GROUP BY 1,2,3;
10. 4 Cost/GGR
sql
SELECT
DATE_TRUNC('day', capture_ts) d,
method_code, provider,
SUM(fees_fixed + amountfees_pct + fx_spread) AS total_cost,
SUM(capture_amount) AS total_captured,
(SUM(fees_fixed + amountfees_pct + fx_spread) / NULLIF(SUM(total_captured),0)) AS cost_to_captured
FROM payments_flat
WHERE capture_status='CAPTURED'
GROUP BY 1,2,3;
11) Additional screens
BIN Drilldown: AR/decline-codes, 3DS-friction, latency by issuers.
Provider Scorecard: SLA Metrics, Incidents, Credits, Cost/GGR.
Treasury Snapshot: L0/L1 balances, prefund, StressRes, TtF replenishment.
Recon View: Settlement Timing, Aging Non-Stitched Butches, Fee Accuracy.
12) Data quality i治理
Dictionary of KPIs with versioning (formulas/base/exceptions).
Single TZ = UTC, p-quantiles only CONT.
Idempotency of events and dedup of webhooks.
Time/amount/FX tolerances policy (for reconciliation/latency).
Data tests in CI: non-empty divisor bases, timestamp monotony, NULL fraction.
13) Implementation: checklist
- KPIs/formulas/bases are defined and fixed in the dictionary.
- ingestion and event/registry normalization configured.
- Built showcases' payments _ flat ',' webhooks', 'settlements', 'treasury'.
- Implemented heatmaps, funnel, latency, payout/refund panels.
- SLO and alert thresholds established; associated with playbooks.
- Access roles: C-level (read-only summary), Ops/Fraud (drill-down).
- Weekly QBR by provider based on Provider Scorecard.
- UAT test suite: demo dataset, p-quantile check, database correctness, alerts.
14) Frequent errors
Mixing bases ('attempt' vs' capture ') → false conclusions.
No 'ticket _ size' segmentation → distorted AR picture.
Ignore abandon on 3DS → an "overstated" problem with the provider.
Lack of control webhook duplicates → double actions.
Incomplete showcase for settlement/fees → Cost/GGR cannot be estimated.
Without SLOs and playbooks, the dashboard turns into a "showcase without action."
Summary
Dashboard payment KPIs are an operational tool, not just graphs. It connects funnel, money and infrastructure, relies on clear formulas and segmentation, gives automatic signals and immediately suggests actions. As a result: AR_net above, TtW/TtR in corridors, Cost/GGR under control, incidents are localized quickly, and the dialogue with providers is based on numbers.