Chargebacks
Two read endpoints, one per question: every dispute against a customer, and the disputes on one order. Both are read-only, and the next section explains why that is not an oversight.
Required scope:
payments:read(global tier), on both endpoints. Both also require thepayments.fiat_cardcapability on the relationship — the same pair the fiat order reads use, because a chargeback is a fact about an order you can already see.
Responding to a chargeback
There is no API for it, and none is coming until a processor offers one. Not one card processor we route through exposes representment — submitting evidence to contest a dispute — so an endpoint here could only accept your evidence and sit on it. We do not publish endpoints that cannot keep their promise.
To contest a dispute, send the evidence to your Niftipay contact by email and we
file it with the processor on the merchant’s behalf. Quote the order_key and
the chargeback id from these endpoints.
What we know, and what we might not
A chargeback row exists because a processor told us about the dispute. Not every card rail we route through delivers dispute notifications today, and one delivers them as a periodic file rather than live. So:
- An empty list is not proof that no dispute exists.
disputed_atcan lag the real dispute date on the rails that batch.- Reconcile against the merchant’s processor statements for anything financial; treat these endpoints as the operational view, not the book of record.
We would rather you knew that than discover it during a reconciliation.
List a customer’s chargebacks
GET /api/v1/partner/customers/{customerId}/chargebacks
Newest dispute first. Scoped to the relationship: a merchant you share with another partner never shows you that partner’s disputes.
curl "https://www.niftipay.com/api/v1/partner/customers/pc-1/chargebacks?limit=25" \
-H "Authorization: Bearer <partner_api_key>"
?limit= is clamped, never refused: the default is 25 and the maximum is 100, so
asking for 5000 returns 100 rather than an error. There is no cursor on this rail
yet — one page is all it offers.
List one order’s chargebacks
GET /api/v1/partner/fiat-orders/{orderKey}/chargebacks
The disputes on a single order, newest first, with no customer id in the path —
a partner holding nothing but the order_key can ask. An order you cannot see
answers with an empty list rather than a 404: either way the answer is “no
chargebacks”, so there is no second signal worth protecting here.
curl https://www.niftipay.com/api/v1/partner/fiat-orders/1001/chargebacks \
-H "Authorization: Bearer <partner_api_key>"
Response 200
Identical shape from both endpoints:
{
"request_id": "req-1",
"api_version": "2026-08-01",
"data": {
"chargebacks": [
{
"id": "cbe-1",
"order_key": "1001",
"psp": "niftipayp1",
"order_status": "chargeback",
"amount_cents": 10000,
"currency": "EUR",
"fee_cents": 3500,
"fee_currency": "EUR",
"dispute_amount_cents": 8487,
"dispute_currency": "GBP",
"disputed_at": "2026-09-01T08:00:00.000Z",
"created_at": "2026-09-02T10:00:00.000Z"
}
]
}
}| Field | Meaning |
|---|---|
id |
The dispute record’s id. Quote it when you send evidence by email. |
order_key |
The disputed order, as a string. |
psp |
Our public name for the processing rail. It is a stable label, not the processor’s own name. |
order_status |
The order’s status, which a dispute turns to chargeback. See below. |
amount_cents |
The order amount as we booked it, frozen onto the record when the dispute landed, or null. |
currency |
Currency of amount_cents, or null. |
fee_cents |
What the processor charged for the dispute itself. |
fee_currency |
Currency of fee_cents — the merchant’s settlement currency, which need not be the order’s. |
dispute_amount_cents |
What the cardholder disputed, as the processor stated it. null on the rails that send no amount. |
dispute_currency |
Currency of dispute_amount_cents. Often not the order’s — see below. null with the amount. |
disputed_at |
When the processor opened the dispute. Falls back to created_at when it does not say. |
created_at |
When we recorded it. |
Two amounts, and why they differ
amount_cents is the order as we booked it. dispute_amount_cents is what the
cardholder disputed, in the currency the processor disputed it in — and the two
pairs disagree whenever the acquirer settles in a currency other than the
order’s. An 87.00 EUR order settled through a GBP acquirer comes back as a
73.84 GBP dispute.
Do not derive one from the other. The rate is the acquirer’s, applied on its own
date, and it is not the settlement rate on the order either. Read the pair, or
read neither: dispute_currency is never implied by currency.
Both dispute fields are null together when the processor sent a dispute notice
with no amount, and on every record we captured before we began storing them.
null means the processor never said, not 0.
Why order_status and not status
Because the order’s status is the only status we have. A dispute here carries no
lifecycle of its own — no open, under_review, won or lost — for the same
reason there is no endpoint to respond: the processors do not report one. A field
called status next to a chargeback would have read as that lifecycle, and
branching on it would have been branching on a promise we never made.
The order’s own figures
An order carries its own dispute total. On
Retrieve a fiat order, chargeback_cents is
what has been charged back and refunded_cents is what was refunded — and a
chargeback reverses the whole order, so a disputed order reports its full
amount in chargeback_cents and 0 in refunded_cents, even if a partial
refund came first. The cents are never counted as both.
Errors
| Status | code | Meaning |
|---|---|---|
| 403 | insufficient_scope | Token minted without payments:read |
| 403 | capability_not_enabled | payments.fiat_card not granted (customer-scoped endpoint only) |
| 404 | resource_not_found | The customer id is not one of your relationships |
| 500 | internal_error | Unexpected failure |
| 503 | temporarily_unavailable | Transient failure. Retry — the only code that means that |
The event
payment.chargeback fires when a dispute lands. It carries the order’s
identifiers, not the dispute’s figures — read these endpoints for those. See
Webhooks.