Report a Dispute
Call /v1/order/dispute/{order-id} when a customer initiates a chargeback or other payment dispute on an order Pinch already knows about. Report both the dispute opening and the eventual outcome (won/lost) — Pinch uses both signals to refine future scoring.
Request
POST /v1/order/dispute/{order-id} HTTP/1.1
Host: api.pinch.ai
Authorization: {api-key}
Content-Type: application/json
The {order-id} in the path is your providerOrderId from the original /v1/order call.
Body
| Field | Type | Required | Description |
|---|---|---|---|
dispute | array | yes | One entry per dispute event. Most orders have just one. |
Dispute entry
| Field | Type | Required | Description |
|---|---|---|---|
disputeId | string | yes | Your unique identifier for this dispute. |
disputeType | string | yes | CHARGEBACK, INQUIRY, or ARBITRATION. |
disputeReason | string | yes | Reason code. Common values: INR (item not received), IND (item not as described), UNAUTH (unauthorized transaction), DUPLICATE, FRAUD. |
disputeSubreason | string | no | Free-text detail provided by the financial institution. |
disputeStatus | string | yes | OPEN, RESPONDED, WON, LOST. |
disputeAmount | number | yes | Amount disputed in the order's currency. |
timestamp | number | yes | Epoch milliseconds. |
Example request — opening a dispute
- curl
- Node
- Python
curl "https://api.pinch.ai/v1/order/dispute/MC229151G" \
-H "Authorization: $PINCH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"dispute": [
{
"disputeId": "dispute-2341",
"disputeType": "CHARGEBACK",
"disputeReason": "INR",
"disputeSubreason": "Tracking shows delivered but package not received",
"disputeStatus": "OPEN",
"disputeAmount": 89,
"timestamp": 1739577600000
}
]
}'
await fetch(`https://api.pinch.ai/v1/order/dispute/${orderId}`, {
method: "POST",
headers: {
Authorization: process.env.PINCH_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
dispute: [
{
disputeId: "dispute-2341",
disputeType: "CHARGEBACK",
disputeReason: "INR",
disputeStatus: "OPEN",
disputeAmount: 89,
timestamp: Date.now(),
},
],
}),
});
import os, requests, time
requests.post(
f"https://api.pinch.ai/v1/order/dispute/{order_id}",
headers={
"Authorization": os.environ["PINCH_API_KEY"],
"Content-Type": "application/json",
},
json={
"dispute": [
{
"disputeId": "dispute-2341",
"disputeType": "CHARGEBACK",
"disputeReason": "INR",
"disputeStatus": "OPEN",
"disputeAmount": 89,
"timestamp": int(time.time() * 1000),
}
]
},
)
Example request — updating the outcome
Re-call the endpoint with the same disputeId and the new status. Pinch is idempotent on disputeId.
{
"dispute": [
{
"disputeId": "dispute-2341",
"disputeType": "CHARGEBACK",
"disputeReason": "INR",
"disputeStatus": "LOST",
"disputeAmount": 89,
"timestamp": 1742256000000
}
]
}
A LOST dispute strongly increases the abuse score for the underlying customer. A WON dispute neutralizes the signal.
Response
{
"providerOrderId": "MC229151G",
"pinchOrderId": "pin_8c2f9a1b",
"disputesRecorded": 1
}
This endpoint doesn't return a decision — like disposition, it's reporting, not gating.
When to send
- On dispute open: as soon as your payment processor notifies you of the chargeback.
- On status change: every time the status moves (
OPEN→RESPONDED→WON/LOST). - Backfill if needed: if you have historical dispute data, batch-send it. Pinch will use it to retrain the model for your account.
Decision impact
Disputes don't directly drive a decision — they feed the model. But they show up in three places:
- Customer profile in the dashboard, under Order History — disputed orders are flagged.
- Pinch Assessment score — repeated
LOSTchargebacks increase the score for the customer and any linked identifiers (via the Pinch Identity Number). - Variables — variables like
Num chargebacks per email in last 1 yearandChargeback rate by valueare derived from this data. You can reference them in Workflows.
Errors
| HTTP | Code | Meaning |
|---|---|---|
| 400 | invalid_request | Required field missing |
| 404 | order_not_found | {order-id} doesn't exist in Pinch |
| 422 | unknown_enum_value | disputeType or disputeStatus not in the enum |
| 409 | duplicate_dispute_id | Conflict if disputeId collides with a different dispute on a different order |
See also
- Order API — must be called first
- Return API — chargebacks often follow disputed returns; report both
- Customers guide — where disputes surface on the customer profile