Alerts
List, inspect, and resolve dispute alerts.
An alert is a dispute warning. A cardholder has questioned a charge with their bank, and the card network told Disputely before opening a chargeback. Act on it in time and the chargeback never happens.
Alert types
| Type | What it means | Do you act? |
|---|---|---|
ETHOCA | Mastercard's alert network flagged a dispute or confirmed fraud. | Yes — refund and resolve. |
CDRN | Verifi's (Visa) alert network flagged a dispute. | Yes — refund and resolve. |
RDR | Visa auto-refunded the cardholder under your Rapid Dispute Resolution rules. | No — informational. Reconcile the refund. |
Lifecycle
Alerts arrive as NEEDS_REVIEW. For ETHOCA and CDRN alerts you have until
respondBy (typically 48 hours) to act:
- You refund the customer and call resolve →
status: "RESOLVED". Done, no chargeback. CANCELLEDmeans the alert was declined (no refund issued) — the dispute will likely continue to a formal chargeback.
RDR alerts are already settled by Visa and can't be resolved through the API.
List alerts
GET /v1/alertsRequires alerts:read. Returns your alerts, newest first.
curl "https://api.disputely.com/v1/alerts?status=NEEDS_REVIEW&limit=50" \
-H "Authorization: Bearer dspm_live_YOUR_KEY"| Param | Notes |
|---|---|
type | RDR, CDRN, or ETHOCA |
status | NEEDS_REVIEW, RESOLVED, or CANCELLED |
actionable | true — shorthand for status=NEEDS_REVIEW and type CDRN/ETHOCA. Ideal for work queues. |
createdSince / createdBefore | RFC 3339 timestamps |
q | Substring match on paymentDescriptor (case-insensitive) |
limit | Default 50, max 100 |
cursor | For pagination |
Get an alert
GET /v1/alerts/{alertId}Requires alerts:read. Returns 404 alert_not_found if the alert doesn't
exist or isn't yours.
The alert object
{
"id": "9XOJYR6WNLMU2XEQMSF244GFI",
"accountId": "acct_2ZK8Q1M4",
"type": "ETHOCA",
"alertType": "dispute",
"status": "NEEDS_REVIEW",
"respondBy": "2026-10-02T18:30:00Z",
"disputeAmount": 29.97,
"disputeCurrency": "USD",
"referenceTransactionAmount": 29.97,
"referenceTransactionCurrency": "USD",
"referenceTransactionDate": "2026-09-28T14:05:00Z",
"authCode": "081224",
"acquirerReferenceNumber": "74537604221234567890",
"paymentType": "credit",
"paymentDescriptor": "ACME*STORE",
"paymentDescriptorContact": "8005551234",
"networkDescriptor": null,
"mcc": "5734",
"reasonCode": "4837",
"source": "mastercard",
"caseDate": "2026-09-30",
"timestamp": "2026-09-30T18:30:00Z",
"networkTimestamp": "2026-09-30T18:29:41Z",
"issuer": "CHASE BANK USA",
"liability": "issuer",
"merchantName": "ACME STORE",
"transactionId": "MTF_1A2B3C4D",
"age": 2,
"respondedAt": null,
"respondedBy": null,
"refundedAmount": null,
"refundedCurrency": null,
"declineReason": null,
"cardInfo": {
"bin": "411111",
"lastFour": "4242",
"accountNumber": null
}
}Every field is always present (as null when unknown), so you can rely on key
existence.
Fields you'll actually use
| Field | Meaning |
|---|---|
id | Alert ID. Use it to fetch or resolve the alert. |
type / status | See tables above. |
respondBy | Deadline to act. null on RDR. |
disputeAmount / disputeCurrency | What the cardholder is disputing. Your refund can't exceed this. |
paymentDescriptor | The billing descriptor the cardholder saw on their statement. |
cardInfo.bin + cardInfo.lastFour | First 6 + last 4 of the card — your main matching keys. |
authCode | Authorization code from the original transaction. |
acquirerReferenceNumber | ARN — exact match key if your processor exposes it. |
referenceTransactionDate | When the original charge happened. |
timestamp | When the alert reached Disputely. |
reasonCode | Network reason code (e.g. 4837 = fraud, 4853 = cardholder dispute). |
Matching tip: find the original order by cardInfo.bin + cardInfo.lastFour
- amount + a date window around
referenceTransactionDate. UseacquirerReferenceNumberorauthCodefor an exact match when available.
Resolve an alert
POST /v1/alerts/{alertId}/resolveRequires alerts:write. Tells Disputely you refunded the cardholder — we
synchronously notify the card network and the dispute is closed. Typical
latency is 1–3 seconds.
curl -X POST "https://api.disputely.com/v1/alerts/9XOJYR6WNLMU2XEQMSF244GFI/resolve" \
-H "Authorization: Bearer dspm_live_YOUR_KEY" \
-H "Idempotency-Key: resolve-9XOJYR6WNLMU2XEQMSF244GFI" \
-H "Content-Type: application/json" \
-d '{ "refundedAmount": 29.97, "refundedCurrency": "USD" }'| Field | Required | Notes |
|---|---|---|
refundedAmount | yes | Greater than 0, at most disputeAmount. Equal = full refund, less = partial. |
refundedCurrency | yes | Must match disputeCurrency. |
On success you get the updated alert back with status: "RESOLVED" and
respondedAt / refundedAmount / refundedCurrency filled in.
Refund first, then resolve
Resolving tells the card network the cardholder got their money back. Issue the refund in your payment system before calling this endpoint.
Resolve errors
| HTTP | code | Meaning |
|---|---|---|
| 400 | invalid_refund_amount | Amount is ≤ 0 or greater than disputeAmount. |
| 400 | currency_mismatch | refundedCurrency doesn't match disputeCurrency. |
| 404 | alert_not_found | Alert doesn't exist or isn't yours. |
| 409 | alert_not_actionable | RDR alert, or the alert was already declined. |
| 422 | cannot_resolve_after_window | Past the respondBy deadline. |
| 502 | provider_unavailable | Card network timed out. Retry with the same Idempotency-Key. |
| 502 | provider_rejected | Card network rejected the resolution — detail explains why. |
Retries are safe. Resolving an alert that's already RESOLVED returns
200 with the current alert instead of an error. After a
provider_unavailable, just retry with the same
Idempotency-Key — the call converges on success.