Payment Disputes & Chargebacks

Two dispute scopes, one workspace

Disputes are stored in payment_disputes with a scope of either:

Platform staff use Disputes → Subscription Disputes (/platform/disputes, Admin+). The workspace is the same component the gym sees, opened with the platform scope, so anything you learn here applies to helping a gym with theirs.

Dispute state

State is derived, not stored as a free-text status (src/lib/disputeState.ts):

StateMeaning
Needs responseNot closed, evidence not submitted, resubmission cap not reached, deadline not passed. This is the only actionable state.
Under reviewEvidence submitted, or the cap is reached, or the deadline has passed. Stripe and the card issuer now decide.
ClosedWon or lost. Acknowledge it to clear it from the queue.

The evidence workflow

  1. Prefill — the prefill-dispute-evidence function pulls what the account already holds (contract, payment history, service records) into the evidence form.
  2. Upload — supporting files go to the private dispute-evidence bucket and are listed in payment_dispute_evidence_files.
  3. Readiness gate — submission is blocked until five things exist: a signed contract, a payment-history PDF, a service-summary PDF, a product description and a service explanation.
  4. Submit — submit-dispute-evidence sends it to Stripe. Each submission increments resubmission_count; once submission_cap_reached is true no further evidence can be sent.
  5. Auto-submit — by default a dispute with evidence in place is submitted automatically the morning of its deadline by the daily 09:00 job. Turn this off per dispute with the auto-submit toggle only when you intend to keep editing right up to the deadline.

Money movement

Stripe withdraws the disputed amount when the dispute opens and reinstates it if it is won. Those movements are recorded on the dispute (funds_withdrawn_at, funds_reinstated_at) and itemised in payment_dispute_ledger_entries, shown as the financial ledger in the workspace. Use it when a gym asks why their payout is short.

Early warnings

payment_dispute_early_warnings captures Stripe inquiries and fraud alerts that have not yet become disputes. Dismiss one only once it has been acted on — dismissal is recorded.

Scheduled jobs

Watch out for