Respond with Evidence

To contest a chargeback you build a counter — your evidence response for one dispute phase. You compose it as a draft (continuously autosaved), then submit it to the processor in a single, final action.

Submission is one-shot and irreversible. Card disputes allow exactly one evidence response per phase — there is no within-phase back-and-forth with the issuer. Once you submit, the counter is locked and goes straight to the processor. Get the draft right before you submit it.

The counter lifecycle

A counter moves through these states:

StateMeaning
draftEditable. Autosaved as you compose. At most one draft exists per dispute phase.
submittedSent to the processor. Terminal for this phase.
withdrawnA draft you discarded.
supersededA prior phase’s submission, replaced when a new phase (e.g. pre-arbitration) opened.

A dispute usually has exactly one counter. A new counter is created only when a new phase/round opens: the dispute re-enters needs_response at a higher phase, a fresh draft is created, and the previous submitted counter becomes superseded. In practice, multi-phase rounds are rare.

Evidence categories

Evidence is a list of evidence_items, each tagging a canonical category with free text and/or attached file_ids. Truemed maps these categories to the processor for you, so you provide evidence in one canonical form. Categories:

product_description, customer_communication, customer_name, customer_email, customer_purchase_ip, customer_signature, billing_address, receipt, shipping_documentation, shipping_tracking_number, service_documentation, service_date, access_activity_log, refund_policy, refund_policy_disclosure, refund_refusal_explanation, cancellation_policy, cancellation_policy_disclosure, cancellation_rebuttal, duplicate_charge_documentation, duplicate_charge_explanation, uncategorized.

The dispute’s evidence_requirements (from the detail endpoint or the dispute.* webhook) resolves the recommended evidence for the dispute’s reason, already grouped by weight: lead with the compelling categories, then add supporting; other lists the remaining categories the processor accepts. Each entry tells you whether it takes free text and/or a file, and merchant_explanation is Truemed’s narrative on how to contest this reason. For example, a product_not_received dispute surfaces shipping_tracking_number and service_documentation as compelling, while product_unacceptable surfaces product_description and your refund_policy_disclosure. Provide the categories that best rebut the specific reason.

1. Create a draft

POST /api/v1/disputes/{dispute_id}/counters creates the draft. You may seed it with initial evidence or start empty.

$curl -s -X POST "https://dev-api.truemed.com/api/v1/disputes/$DISPUTE_ID/counters" \
> -H "Authorization: Bearer $TRUEMED_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "evidence_items": [
> {"category": "product_description", "text": "Organic magnesium supplement, 60ct."}
> ]
> }'

The response is the counter, including its counter_id and revision (starts at the first revision). Persist both.

2. Autosave the draft

POST /api/v1/disputes/{dispute_id}/counters/{counter_id} upserts the draft. It’s a full replacement of evidence_items and is built for autosave. There’s no fixed rate limit, but debounce saves to roughly one every 300–500 ms of idle typing rather than firing on every keystroke — enough to feel live without redundant writes.

Autosave validates the evidence shape (category capabilities, one file per category, no duplicate categories) and rejects an invalid save with 422 — the persisted draft is left untouched. Empty or partially-filled items (a category with no text or file yet) save fine, so an in-progress draft is never blocked; surface the 422 inline and keep the merchant’s edits rather than discarding them.

To stay safe under concurrent editors, the draft is optimistically locked: send the revision you last read. If the counter changed since (another editor saved first), the request is rejected with 409 Conflict — reload the counter and retry with the new revision.

$curl -s -X POST "https://dev-api.truemed.com/api/v1/disputes/$DISPUTE_ID/counters/$COUNTER_ID" \
> -H "Authorization: Bearer $TRUEMED_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "revision": 1,
> "evidence_items": [
> {"category": "product_description", "text": "Organic magnesium supplement, 60ct."},
> {"category": "shipping_tracking_number", "text": "1Z999AA10123456784"},
> {"category": "receipt", "file_ids": ["f47ac10b-58cc-4372-a567-0e02b2c3d479"]}
> ]
> }'

Evidence is saved server-side only — there is no client-side draft store — because dispute evidence can contain PHI.

3. Submit (one-shot)

POST /api/v1/disputes/{dispute_id}/counters/{counter_id}/submit submits your evidence to the processor. The counter moves to submitted.

$curl -s -X POST "https://dev-api.truemed.com/api/v1/disputes/$DISPUTE_ID/counters/$COUNTER_ID/submit" \
> -H "Authorization: Bearer $TRUEMED_API_KEY"

The dispute does not flip to under_review synchronously — that transition is driven by the resulting processor webhook. Watch for dispute.updated and re-fetch the dispute for authoritative state.

Withdraw a draft

POST /api/v1/disputes/{dispute_id}/counters/{counter_id}/withdraw discards a draft you no longer want. Only drafts can be withdrawn — a submitted counter is permanent.

Error responses

StatusWhen
409 ConflictThe revision you sent is stale — another save landed first. Reload and retry.
422 Unprocessable EntityEvidence validation failed. This is checked on create and autosave, not only at submit, so an invalid draft is never persisted. Causes: a file_id you don’t own (see Upload Evidence Files); free text on a file-only category (or a file on a text-only category); more than one file on a category; or two items sharing a category. The whole request is rejected; nothing is silently dropped.
400 Bad RequestThe counter isn’t editable (not a draft), or the dispute can’t accept a submission right now.
404 Not FoundThe dispute or counter isn’t on your sales channel.