Skip to main content

Disputes

Disputes allow you to challenge unauthorized or fraudulent transactions. When you create a dispute, a chargeback process is initiated with the card network.

Dispute Lifecycle

pending → inReview → won       (chargeback successful)
pending → inReview → lost      (chargeback denied)
pending → canceled             (dispute withdrawn)

Create a Dispute

Initiate a dispute for a transaction:
curl -X POST https://api.ledger.so/v1/transactions/txn_abc123/disputes \
  -H "Api-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "unauthorized",
    "description": "I did not authorize this transaction"
  }'
{
  "object": "dispute",
  "id": "dsp_xyz789",
  "transactionId": "txn_abc123",
  "cardId": "card_def",
  "userId": "user_123",
  "amount": 5000,
  "reason": "unauthorized",
  "description": "I did not authorize this transaction",
  "status": "pending",
  "createdAt": 1703520000000
}

Dispute Reasons

ReasonDescription
unauthorizedTransaction not authorized by cardholder
duplicateCharged multiple times
product_not_receivedGoods/services not delivered
product_unacceptableProduct defective or not as described
credit_not_processedRefund not received
otherOther reason (provide description)

List Disputes

curl https://api.ledger.so/v1/disputes \
  -H "Api-Key: $API_KEY"

Filter Options

ParameterDescription
userIdFilter by user
transactionIdFilter by transaction
statusFilter by status
limitResults per page
cursorPagination cursor
curl "https://api.ledger.so/v1/disputes?status=pending" \
  -H "Api-Key: $API_KEY"

Get Dispute

curl https://api.ledger.so/v1/disputes/dsp_xyz789 \
  -H "Api-Key: $API_KEY"
{
  "object": "dispute",
  "id": "dsp_xyz789",
  "transactionId": "txn_abc123",
  "cardId": "card_def",
  "userId": "user_123",
  "amount": 5000,
  "reason": "unauthorized",
  "description": "I did not authorize this transaction",
  "status": "inReview",
  "evidence": {
    "hasFile": true,
    "textEvidence": "Additional context..."
  },
  "createdAt": 1703520000000,
  "updatedAt": 1703523600000
}

Update Dispute

Add text evidence or cancel a dispute:
curl -X PATCH https://api.ledger.so/v1/disputes/dsp_xyz789 \
  -H "Api-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "textEvidence": "I was traveling on this date and could not have made this purchase. See attached boarding pass."
  }'

Cancel a Dispute

curl -X PATCH https://api.ledger.so/v1/disputes/dsp_xyz789 \
  -H "Api-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "canceled"
  }'
Only pending or inReview disputes can be canceled. Resolved disputes cannot be changed.

Evidence

Upload File Evidence

curl -X PUT https://api.ledger.so/v1/disputes/dsp_xyz789/evidence \
  -H "Api-Key: $API_KEY" \
  -H "Content-Type: multipart/form-data" \
  -F "[email protected]"
Supported formats: PDF, PNG, JPG (max 10MB)

Download Evidence

curl https://api.ledger.so/v1/disputes/dsp_xyz789/evidence \
  -H "Api-Key: $API_KEY" \
  -o evidence.pdf

Dispute Status

StatusDescription
pendingDispute submitted, awaiting review
inReviewUnder investigation
wonChargeback successful, funds returned
lostChargeback denied
canceledDispute withdrawn

Timeline

Disputes typically take 30-90 days to resolve. The timeline depends on:
  • Card network (Visa, Mastercard)
  • Dispute reason
  • Evidence quality
  • Merchant response

Webhooks

EventDescription
dispute.createdNew dispute filed
dispute.resolvedDispute concluded (won, lost, or canceled)

Best Practices

File disputes within 60 days of the transaction. Earlier disputes have higher success rates.
Include relevant documentation: receipts, correspondence, screenshots, travel records.
Provide detailed descriptions of why the transaction is being disputed.
Set up webhooks to track dispute progress and respond promptly to requests for additional info.