Revenue

Dispute and refund risk monitor

Track chargeback and dispute activity and refund rate against the Visa VAMP and Mastercard ECM thresholds that get a payment account fined or shut off, and find which products, plans or cohorts generate them. Covers dispute rate versus dispute activity, per-network denominators and dispute-fighting economics.

  • +1
    What's our dispute rate and how close are we to a monitoring programme?
  • +1
    Which plan or product is generating the most chargebacks?
  • +1
    Did refunds or disputes spike last month?

The playbook

A refund rate on a revenue report tells you about customer expectations. A dispute rate tells you whether you are about to lose your payment processor, and only one specific way of computing it is the number the card networks actually use. This playbook computes the compliance metric on each network's own denominator, compares it against the published count and rate thresholds, and is explicit that any figure derived from a payments API is a floor rather than the networks' number.

Steps

  1. Pull the dispute numerator over at least 13 months. stripe.list_disputes with created_gte / created_lte, limit: 100, paging on starting_after until exhausted. Keep amount, currency, reason, status, charge, created and evidence_details.due_by. On Polar use polar.list_disputes; on Dodo use dodo_payments.list_disputes. Thirteen months is the minimum because the network programmes evaluate month bands and exit conditions over consecutive months, and because the most recent months are still filling in.

  2. Build the denominator, split by card brand. stripe.list_charges has no status filter, so either page the full window and filter client side to successful charges, or, for meaningful volume, prefer stripe.search with resource: "charges" and a query such as status:"succeeded" AND created>..., paging the synthetic _next_page row. Keep payment_method_details.card.brand so Visa and Mastercard can be counted separately. On Polar use polar.list_payments, or polar.get_metrics for pre-computed order and revenue series; on Dodo use dodo_payments.list_payments. If the connected provider does not expose card brand on the returned rows, report a single blended rate and say plainly that VAMP and ECM thresholds are per-network and cannot be checked exactly.

  3. Compute dispute activity and dispute rate, each on the right denominator. Build two monthly series: disputes bucketed by the dispute's own created date, which gives activity, and disputes bucketed by the underlying charge's created date, which gives rate. Divide the Visa numerator by Visa payment count in the same calendar month, and the Mastercard numerator by Mastercard payment count in the previous month. Report activity as the compliance number and rate as the diagnostic number, and label which is which on every line.

  4. Compare against the published thresholds and the slope. Visa VAMP: non-compliant at a VAMP count of 5 and a 0.5% ratio, excessive at 1,500 count (150 in CEMEA) and 1.5% ratio (2.2% CEMEA), where the VAMP count includes TC15 disputes plus TC40 early fraud warnings and a transaction appearing in both is counted twice. Mastercard ECM: 100 to 299 chargebacks and a 1.5 to 2.99% rate, with fines from month two at 1,000 USD rising to 100,000 USD by month 19 and beyond. Mastercard HECM: 300 or more and 3%. Mastercard exits require being under threshold for three consecutive months. Also check the industry line that dispute activity above 0.75% is excessive, and report month-over-month slope, since Stripe states a sudden spike or steep upward trend can trigger placement before the threshold is reached.

  5. Compute refund rate separately and attribute both to products. stripe.list_refunds over the same window, paged fully, joined to charges via charge or payment_intent for refund rate by count and by volume, and to split full from partial refunds. On Polar use polar.list_refunds, noting that its net_revenue metric already nets refunds so you must not subtract them twice; on Dodo use dodo_payments.list_refunds. Then join disputed charges through stripe.list_invoices to subscription, price and product, using stripe.list_products and stripe.list_prices for names and stripe.search with a metadata query where product identity lives in metadata. Group disputes by reason code: a cluster of general or duplicate reasons usually points at an unrecognised statement descriptor or a confusing billing statement rather than at fraud.

  6. Size the cash impact and the economics of fighting. stripe.list_balance_transactions with type: "adjustment" captures the actual cash movement including dispute fees, which are a separate event from the disputed amount. stripe.get_balance reveals reserves or held funds, which is often the first visible symptom of a processor review. On Dodo, dodo_payments.list_ledger_entries with event_type in dispute, dispute_reversal, dispute_fees and ethoca_fees gives the same picture, and its usd_equivalent_amount is the only built-in multi-currency normaliser across the three providers. For each dispute compute expected value of contesting as win probability multiplied by disputed amount, minus the dispute fee and the effort cost, rather than advising that every dispute be fought. Where charges and disputes are mirrored to a warehouse, call postgres.get_schema then postgres.query instead of paging thousands of API records.

  7. Report. One row per month with columns: month, successful payments (Visa), successful payments (Mastercard), disputes by dispute date, dispute activity %, disputes by charge date, dispute rate %, VAMP count, Visa threshold status, Mastercard ECM rate against previous-month payments, Mastercard threshold status, refunds count, refund volume, refund rate %, dispute fees and adjustments, maturity flag for months inside the 120 day window. Then deliver one judgement: the nearest threshold, the distance to it in both count and rate, the direction of the trend, and an explicit statement that the figures are a lower bound because Stripe absorbs some no-liability disputes that never appear in the API.

Gotchas

  • Any API-derived dispute rate is a floor, not the networks' number. Stripe states that some disputes where you have no liability do not appear in the Dashboard or API responses because Stripe handles them on your behalf, yet the monitoring programmes still include them in their calculations. The gap is widest for merchants who refund heavily. Never present the computed rate as the compliance figure without this caveat.
  • Activity and rate are different numbers and only one is the compliance metric. Stripe's own worked example produces 1.0% and 0.3% for the same week. Reporting the wrong one either panics the team or falsely reassures it. And Visa and Mastercard do not share a denominator: Visa uses the same calendar month, Mastercard uses the previous month, so a growing business reads higher on Mastercard purely from denominator lag.
  • The last 120 days are provisional, and won disputes still count. Cardholders can dispute a charge up to 120 days after payment and sometimes longer, so any recent month's rate will keep moving. Stripe is explicit that all disputes, won or lost, count toward the rate, which means fighting protects cash but not compliance. Refunding does not help either: monitoring programmes do not consider refunds when identifying disputes.
  • Early fraud warnings count for Visa and there is no endpoint for them here. VAMP counts TC40 early fraud warnings alongside TC15 disputes, and a transaction appearing in both reports is counted twice. No tool in this inventory returns early fraud warnings, so the computed VAMP count is structurally understated and that gap must be stated, not estimated.
  • One business can be several Visa accounts. Visa identifies an account by the static component of its statement descriptor and its acquiring bank, so a multi-descriptor or multi-country merchant has several rates and none of them equals the blended one. Check whether descriptors differ before presenting a single figure.
  • Count-based rates travel across currencies, volume-based rates do not. Dispute amounts are integer minor units of the original currency, so divide by 100 once and not at all for zero-decimal currencies such as JPY. Only dodo_payments.list_ledger_entries exposes a USD equivalent, so the count-based rate is the comparable metric and any volume total needs a stated FX source. Dispute fees and reserves are separate cash events from the disputed amount, and reporting only disputed volume understates the cost.
  • Low volume makes the rate meaningless, and the month cut is UTC. At 600 transactions, 8 disputes is 1.33%, so below roughly 1,000 monthly transactions a single dispute swings the rate materially: always print the count next to the rate and apply the VAMP count floor of 5 before raising an alarm. Count each dispute once against a charge, never against the invoice and the payment intent as well, since a disputed renewal has all three. Networks evaluate calendar months while Stripe filters are UTC epoch seconds, which moves the last day's charges into the wrong month for a US merchant sitting near a threshold. Filter livemode, because test-mode disputes are trivial to create.

Sequel CLI

Install Sequel skills into your agent

One command connects your agent to Sequel and installs the Sequel skill, so it knows this playbook exists and reads it when a question matches. The CLI signs you in, provisions a scoped API key and writes the config for you.

Already have an MCP client?

https://api.sequel.sh/mcp

Point it at this URL and sign in when prompted, or send an API key from Settings as a Bearer token. Skills come with it; nothing else to install. Manual setup per client

  1. 1

    Install the Sequel CLI

    One line installs the latest CLI with whatever package manager you have.

    curl -fsSL https://sequel.sh/install | sh
  2. 2

    Sign in

    Authenticate in your browser and pick an organization.

    sequel login
  3. 3

    Install into your agent

    Writes the MCP config and installs the Sequel skill file for agents that support skills. Pick an agent from the list, or target one directly by its slug.

    sequel install
    • Claude Code
      sequel install claude-code
    • Claude
      sequel install claude
    • Cursor
      sequel install cursor
    • VS Code
      sequel install vscode
    • Windsurf
      sequel install windsurf
    • Zed
      sequel install zed
    • Codex
      sequel install codex
    • OpenClaw
      sequel install openclaw
    • Hermes
      sequel install hermes

FAQ

Frequently asked questions

What dispute rate is too high?
Stripe states that the card processing industry standard recognises dispute activity above 0.75% as excessive, and that a sudden spike or steep upward trend can trigger a monitoring programme before that threshold is reached. The network programmes are stricter and count-gated: Visa VAMP flags non-compliant at a VAMP count of 5 and a 0.5% ratio, and excessive at 1,500 and 1.5%. Mastercard ECM starts at 100 to 299 chargebacks with a 1.5 to 2.99% rate, and HECM at 300 or more with 3%.
What is the difference between dispute rate and dispute activity?
Stripe defines dispute activity as the percentage of disputes on successful payments by dispute date, and dispute rate as the same thing by charge date. The card networks' monitoring programmes use the activity calculation. Stripe's worked example shows the gap: 1,000 payments in a week with 10 disputes received, of which only 3 belong to that week's payments, is 1.0% activity and 0.3% rate.
How do Visa and Mastercard calculate the chargeback ratio?
They use different denominators. Visa divides disputes or fraud by the total number of payments in the same calendar month. Mastercard divides chargebacks by the total number of payments in the previous month, which mechanically inflates the ratio for a fast-growing business because last month's payment count is smaller. Using one denominator for both misstates one of them.
Does refunding a customer prevent a chargeback?
Not reliably. Stripe states that monitoring programmes do not consider refunds when identifying disputes, and a dispute can still land on a charge that was already refunded. Refunds also do not count toward the network programmes at all, so a high refund rate is a product or expectation problem rather than an account-risk problem, and it is a cheaper substitute for a dispute rather than a cure for one.
Can an AI agent monitor dispute and refund risk?
Yes. With Stripe, Polar or Dodo Payments connected the agent builds a 13 month series of dispute activity and dispute rate on the correct per-network denominators, compares them against the published VAMP, ECM and HECM count and rate thresholds, attributes disputes to products and reason codes, and prices the expected value of contesting. Sequel provides the Stripe, Polar and Dodo Payments connections over MCP and the dispute-and-refund-risk playbook.

Put this playbook to work

Connect a source, ask the question, and the agent follows these steps. Free to start.