Skip to main content

Respond to a Stripe dispute

A customer's bank chargebacks a transaction. Stripe notifies the shop. The shop has a deadline (usually 7-21 days) to respond with evidence. the Hub has receipts, audit logs, signatures, and photos — most of what Stripe asks for.

Drafted from planning · v0.1

Step 1: Find the disputed transaction​

When the dispute lands in Stripe's dashboard, note the PaymentIntent ID. In the Hub:

SELECT * FROM transactions WHERE stripe_pi_id = ?;

This gives you the transaction row, the customer, the date, the lines.

Step 2: Gather the Hub's evidence​

The shop should attach to Stripe's response:

  • Receipt — GET /api/sales/{id}/receipt.pdf — shows the line items, totals, taxes, customer (if attached)
  • Audit trail — SELECT * FROM audit_events WHERE entity_type='transactions' AND entity_id=? — shows who rang the sale and when
  • Customer card — print or screenshot the customer profile; shows the customer was a known repeat customer (if applicable)
  • Service ticket (if it was a service-cashout) — the signed work order with the issue and the labor performed
  • Signature — if Stripe Terminal captured a signature, it's in the transaction's signature_url field; download from R2 and attach
  • Photo evidence — for service tickets, before/after photos demonstrate work was done

Step 3: Compose the response​

Stripe's interface asks for free-form text. Use:

Transaction T-N0123 was rung at Swicked Cycles on 2026-04-15 by Robbie. The customer, Jane Doe (phone 250-555-1234), purchased a service-tune-up ticket on her Specialized Sirrus 4.0 (serial XYZ123). She signed the work authorization (attached). The bike was returned to her on 2026-04-17 with the work complete (before/after photos attached). She has been a regular customer for 4 years (8 prior transactions, none disputed).

Attached:

  • Receipt T-N0123.pdf
  • Work authorization signature
  • Service ticket #2506 with labor lines
  • Before/after photos
  • Audit trail showing the transaction lifecycle

Step 4: Submit through Stripe dashboard​

The shop owner submits through Stripe's dashboard with the evidence attached. Stripe weighs the evidence; outcome varies.

Step 5: Record the outcome​

When Stripe issues the verdict (won/lost):

  • Won: parent transaction stays paid; no further action
  • Lost: Stripe debits the funds; a transactions row of kind='refund' should be created automatically by our webhook handler (or manually if the webhook missed it)

Common dispute reasons​

Reasonthe Hub evidence
"Product not received"Service ticket pickup record, signature, receipt
"Unauthorized charge"Customer profile (returning customer); signature at terminal; cashier identity
"Duplicate charge"Audit trail shows only one transaction; idempotency key
"Wrong amount"Receipt with line items and totals
"Not as described"Service ticket with detailed work; photos before/after

Prevention​

  • Always attach the customer to in-shop transactions (when possible) — turns "unauthorized charge" disputes into "we know this customer" evidence
  • Use Stripe Terminal's signature capture for service tickets > $100
  • Photograph before/after for service work
  • Keep the audit trail clean — every transaction has a who/when/what

See also​