Payment Orchestrator
Chargebacks

Chargebacks

A chargeback (dispute) is the buyer's bank reversing a payment — usually because the cardholder claims fraud, non-delivery or a billing error. The chargeback API gives you a full case-management workflow for each dispute: record it, assign an owner, keep notes, track the documents the scheme requests, upload evidence, fight it with a representment, and close it with an outcome.

When a chargeback lands, a payment.disputed webhook fires (carrying chargebackId, disputeState and the disputed amount) — so your systems learn about it the moment it happens, not when someone checks a bank portal. The payment's financial status (CAPTURED/REFUNDED) is not overwritten by the dispute.

All chargeback endpoints use plain Bearer authentication (an at_live_… access token); they manage a case record, not money movement.

All amounts are minor-unit (kuruş): the chargeback body carries "amountMinor": "10050" (₺100,50) as a string.

Lifecycle

A dispute case moves through a simple lifecycle:

  1. Received — the case is created (POST /chargebacks) and linked to the payment (case status RECEIVED).
  2. In progress — your team works the case: assignment, notes, document requests, evidence (UNDER_REVIEW).
  3. Represented (optional) — you formally challenge the chargeback by submitting a representment with your evidence (REPRESENTMENT_SUBMITTED).
  4. Resolved — the case closes with one of three outcomes:
OutcomeMeaning
WONThe representment succeeded — the funds come back to you
LOSTThe dispute was decided in the cardholder's favour — the funds stay reversed
ACCEPTEDYou chose not to fight the chargeback and accepted the reversal

Endpoints

MethodPathWhat it does
POST/chargebacksRecord a new dispute case against a payment
GET/chargebacksList dispute cases
GET/chargebacks/:idFull case detail
PATCH/chargebacks/:id/statusUpdate the case's lifecycle status
POST/chargebacks/:id/assignAssign the case to a team member
POST/chargebacks/:id/notesAdd an internal note to the case timeline
POST/chargebacks/:id/document-requestsTrack a document the scheme/bank has requested
POST/chargebacks/:id/evidenceUpload an evidence document to the case
POST/chargebacks/:id/representmentSubmit the representment (formally challenge the chargeback)
POST/chargebacks/:id/resolveClose the case with an outcome: WON, LOST or ACCEPTED

Working a dispute

Learn about the dispute

Your payment.disputed webhook fires with the chargebackId and disputeState. Record the case (amount is a minor-unit string here):

curl -X POST https://api-gateway.lunixi.com/api/v1/chargebacks \
  -H "Authorization: Bearer at_live_5f3e2b1a..." \
  -H "Content-Type: application/json" \
  -d '{
    "paymentId": "pay_9f3a1c",
    "amountMinor": "10050",
    "currency": "TRY",
    "networkReasonCode": "13.1",
    "reasonCategory": "product_not_received"
  }'

Optional fields include provider, providerCaseId, cycleCount, representmentDeadline (ISO date) and fee fields. Cases are deduplicated on provider + providerCaseId + cycle (or paymentId + cycle for manual entries) — re-posting the same dispute returns the existing case with created: false.

Assign an owner and investigate

Give the case to whoever will work it, and keep the investigation on the record:

curl -X POST https://api-gateway.lunixi.com/api/v1/chargebacks/cb_5d21e0/assign \
  -H "Authorization: Bearer at_live_5f3e2b1a..." \
  -H "Content-Type: application/json" \
  -d '{ "assignedUserId": "usr_ops_17", "priority": "HIGH" }'
 
curl -X POST https://api-gateway.lunixi.com/api/v1/chargebacks/cb_5d21e0/notes \
  -H "Authorization: Bearer at_live_5f3e2b1a..." \
  -H "Content-Type: application/json" \
  -d '{ "note": "Order shipped 2026-06-28, tracking shows delivered. Pulling courier proof." }'

Collect what the scheme asks for

If the bank or scheme requests specific documents, track each one with POST /chargebacks/:id/document-requests ({ "requestType": "…", "description": "…", "dueDate": "…" }), then satisfy them by attaching evidence. Evidence is a JSON record referencing an already-uploaded file (fileRef), typed so re-uploads of the same type are versioned:

curl -X POST https://api-gateway.lunixi.com/api/v1/chargebacks/cb_5d21e0/evidence \
  -H "Authorization: Bearer at_live_5f3e2b1a..." \
  -H "Content-Type: application/json" \
  -d '{
    "type": "DELIVERY",
    "fileRef": "media/disputes/cb_5d21e0/delivery-proof.pdf",
    "fileName": "delivery-proof.pdf",
    "mimeType": "application/pdf",
    "note": "Courier delivery confirmation with signature"
  }'

Fight it — or accept it

To challenge the chargeback, submit the representment (no body — the case's current evidence set is what gets represented):

curl -X POST https://api-gateway.lunixi.com/api/v1/chargebacks/cb_5d21e0/representment \
  -H "Authorization: Bearer at_live_5f3e2b1a..."

If the dispute is legitimate (or not worth fighting), skip this step and resolve as ACCEPTED.

Resolve the case

When the scheme's decision arrives, close the case:

curl -X POST https://api-gateway.lunixi.com/api/v1/chargebacks/cb_5d21e0/resolve \
  -H "Authorization: Bearer at_live_5f3e2b1a..." \
  -H "Content-Type: application/json" \
  -d '{ "outcome": "WON", "reason": "Delivery proof accepted" }'

Response shape

Mutating calls answer with a compact case reference:

{
  "id": "cb_5d21e0",
  "caseNumber": "CB-000123",
  "status": "UNDER_REVIEW",
  "created": false
}

GET /chargebacks/:id returns the full case detail — the case record (payment link, amountMinor, reason codes, assignment, priority, deadlines) plus its timeline, checklist, evidence, notes and tasks. Case status values: RECEIVED, UNDER_REVIEW, REPRESENTMENT_SUBMITTED, WON, LOST, ACCEPTED, CLOSED.

Use PATCH /chargebacks/:id/status with { "toStatus": "UNDER_REVIEW" } (or "REPRESENTMENT_SUBMITTED") when your workflow requires an explicit stage change, and GET /chargebacks (Bearer, paginated) to build your dispute queue.

Errors

SituationWhat happens / what to do
Unknown chargeback or payment id404 — check the id; cases are merchant-scoped.
Resolving an already-resolved caseState-conflict error — a case takes exactly one final outcome.
Invalid outcome valueValidation error — use WON, LOST or ACCEPTED exactly.
Evidence upload rejectedCheck file size/format and retry; keep one document per upload call.
Missing or invalid API key401 — chargeback endpoints require your server-side Bearer key.

Webhooks

EventFired when
payment.disputedA chargeback is opened against a payment or changes phase — carries chargebackId, disputeState, disputedAmountMinor, openChargebackCount

React to payment.disputed by opening your internal case immediately: dispute windows are short, and evidence assembled early wins cases.

Next steps

  • Webhooks — the delivery model behind payment.disputed
  • Listing Payments — find the disputed payment and its history
  • Refunds — refunding proactively can prevent a dispute from being raised