Overview
When a cardholder challenges a charge with their bank, the bank opens a dispute (commonly called a chargeback). Truemed’s Disputes API lets API-first merchants list and inspect their disputes, respond with evidence, accept a loss, and receive real-time notifications — all from their own systems, without logging into a Truemed UI.
The Disputes API is in draft. Endpoints are live in the sandbox and stable in shape, but they are not yet listed in the public API Reference and may change before general availability. Build against the sandbox (see Base URLs) and reach out to your Truemed contact before relying on them in production.
Base URLs
Truemed has no separate test-mode API keys: the environment is the mode. Requests to the sandbox host run against test data and are automatically flagged as testing; production runs live. Use the same API key format against whichever host you target, and point test-vs-live webhook subscriptions at different endpoints if you need to separate the two. The examples in these guides use the sandbox host while the API is in draft.
What’s in scope for V1
- Stripe only. Disputes originate from Stripe-processed charges in V1.
- Inquiries and chargebacks. Chargebacks are the core case, but pre-chargeback inquiries are surfaced and
answerable too: respond to an inquiry with evidence to pre-empt its escalation to a chargeback. Inquiries notify like
chargebacks — a surfaced inquiry fires
dispute.created/dispute.updated, and if the bank later drops it, the terminalclosedstate firesdispute.closedtoo. The one exception is an inquiry already terminal the first time Truemed sees it (opened and closed between deliveries), which fires no webhook (see Webhooks). - One-shot evidence. Card disputes are answered once per phase. You compose evidence as a draft, then submit it straight to the processor in a single, final action — there is no back-and-forth with the issuer within a phase.
The canonical model
Every dispute is exposed as a stable, normalized shape, so you integrate against one consistent set of fields. Each
dispute carries a Truemed UUID (dispute_id) — always reference disputes by this dispute_id, never by the raw
processor ID (processor_dispute_id), which is provided for your own reconciliation only.
State
state is the canonical lifecycle position:
won, lost, accepted, expired, and closed are terminal — the dispute will not change further.
Phase
phase is orthogonal to state and tracks which round the dispute is in: inquiry, dispute, pre_arbitration, or
arbitration. A new phase opens a fresh evidence round (see Respond with Evidence).
Reason
reason is the canonical reason the dispute was filed: general, fraudulent, duplicate, credit_not_processed,
incorrect_account_details, insufficient_funds, product_not_received, product_unacceptable,
subscription_canceled, or unrecognized. The reason drives which evidence is most persuasive; the dispute’s
evidence_requirements resolves the recommended evidence for that reason, grouped into compelling / supporting /
other, and Respond with Evidence covers how to use it.
Outcome
outcome is the denormalized terminal result (won / lost / accepted / expired / closed) and is null until
the dispute resolves.
How you integrate: notify, then fetch
The API follows a webhook + poll pattern:
- You receive a
dispute.created/dispute.updated/dispute.closedwebhook telling you something changed on a dispute. - You fetch the dispute to read its current canonical state.
The webhook payload carries the full dispute snapshot, so a fetch is usually optional — but the contract is “notify, then fetch for authoritative state,” which keeps you correct even if a webhook is delayed or retried.
Where to go next
- List & Retrieve Disputes — find disputes and read their detail.
- Respond with Evidence — draft, autosave, and one-shot submit a counter.
- Upload Evidence Files — attach receipts, shipping docs, and screenshots.
- Accept a Dispute — concede a loss without contesting.
- Webhooks & Polling — react to dispute changes in real time.