Disputes
A dispute (also called a chargeback) starts when a customer asks their card issuer or bank to reverse a payment. The provider tells VNSwitch, and VNSwitch creates a dispute object linked to the payment and sends you a webhook.
For each dispute you either accept it, which means you agree to return the money, or
challenge it by sending evidence before the deadline in challenge_required_by. You upload
evidence and submit a challenge in the VNSwitch dashboard. The API lets you read disputes, accept
them and see the evidence attached to them.
Dispute deadlines are strict. If you do nothing before challenge_required_by, the
dispute usually ends in the customer’s favour.
Dispute stages and statuses
dispute_stage says where the dispute is in the card scheme or bank process:
| Stage | Meaning |
|---|---|
pre_dispute | An early inquiry, before a formal dispute. |
dispute | A formal dispute (chargeback). |
pre_arbitration | The customer’s side has answered your challenge; you can respond once more. |
arbitration | The card scheme or bank decides the case. |
dispute_reversal | A dispute that was reversed. |
dispute_status says what is happening now:
| Status | Meaning |
|---|---|
dispute_opened | Open and waiting for you to accept or challenge it. |
dispute_challenged | You challenged it; waiting for the decision. |
dispute_accepted | You accepted it. Final. |
dispute_won | Decided in your favour. Final. |
dispute_lost | Decided in the customer’s favour. Final. |
dispute_expired | The deadline passed without a response. Final. |
dispute_cancelled | The customer or issuer withdrew the dispute. Final. |
VNSwitch sends a webhook each time a dispute changes status. The event_type matches the new
status: dispute_opened, dispute_challenged, dispute_accepted, dispute_won,
dispute_lost, dispute_expired and dispute_cancelled. See
Webhooks.
Retrieve a dispute
Returns one dispute. Use it after a dispute webhook to read the reason and the deadline.
GET /disputes/{dispute_id}
Authentication: secret API key (api-key header).
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
dispute_id | string | Yes | The dispute ID, from the webhook or from List disputes. |
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
force_sync | boolean | No | true asks the provider for the latest state before responding. It applies to disputes that are dispute_opened, dispute_challenged or dispute_accepted. Default false. |
Example request
Response
{
"dispute_id": "dp_4a9f2c7e1b",
"payment_id": "pay_8f2c1d9e0a",
"attempt_id": "pay_8f2c1d9e0a_1",
"amount": "150000",
"currency": "VND",
"dispute_stage": "dispute",
"dispute_status": "dispute_opened",
"connector": "<PROVIDER>",
"connector_status": "needs_response",
"connector_dispute_id": "<PROVIDER_DISPUTE_ID>",
"connector_reason": "Product not received",
"connector_reason_code": "13.1",
"challenge_required_by": "2026-11-15T23:59:59.000Z",
"connector_created_at": "2026-11-01T08:00:00.000Z",
"connector_updated_at": "2026-11-01T08:00:00.000Z",
"created_at": "2026-11-01T08:00:05.000Z",
"profile_id": "pro_demo_001",
"is_already_refunded": false
}The dispute amount is a string in the minor unit of the currency: "150000" is 150,000 VND.
Response
A dispute object. Key fields:
| Field | Description |
|---|---|
dispute_id | The dispute ID. |
payment_id | The disputed payment. |
amount, currency | The disputed amount (a string, in the minor unit) and its currency. |
dispute_stage, dispute_status | See Dispute stages and statuses. |
connector_reason, connector_reason_code | The reason given by the issuer or bank, as reported by the provider. |
challenge_required_by | Deadline for your challenge (ISO 8601). Can be null if the provider does not report one. |
connector_status | The provider’s own status text. Use dispute_status in your logic. |
is_already_refunded | true if the disputed amount plus what you have already refunded is more than the amount captured. Check it before you refund a disputed payment, so you do not return the money twice. |
created_at | When VNSwitch received the dispute. |
List disputes
Returns your disputes as a JSON array, filtered by the query parameters. All parameters are optional. Use it to build a daily list of disputes that still need an answer.
GET /disputes/list
Authentication: secret API key (api-key header).
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
dispute_status | string | No | One or more statuses, comma-separated, for example dispute_opened,dispute_challenged. |
dispute_stage | string | No | One or more stages, comma-separated, for example dispute,pre_arbitration. |
payment_id | string | No | Only disputes of this payment. |
reason | string | No | Only disputes with this reason. |
currency | string | No | One or more currency codes, comma-separated, for example VND. |
start_time | string | No | ISO 8601 date-time. Only disputes received at or after this time. |
end_time | string | No | ISO 8601 date-time. Only disputes received up to this time. Defaults to now. Use it together with start_time. |
limit | integer | No | Number of disputes to return, 1 to 100. Default 10. |
offset | integer | No | Number of disputes to skip, for paging. Default 0. |
VNSwitch rejects unknown query parameters on this endpoint. Check the spelling of each filter if you get a validation error.
Example request
Response
[
{
"dispute_id": "dp_4a9f2c7e1b",
"payment_id": "pay_8f2c1d9e0a",
"attempt_id": "pay_8f2c1d9e0a_1",
"amount": "150000",
"currency": "VND",
"dispute_stage": "dispute",
"dispute_status": "dispute_opened",
"connector": "<PROVIDER>",
"connector_status": "needs_response",
"connector_dispute_id": "<PROVIDER_DISPUTE_ID>",
"connector_reason": "Product not received",
"challenge_required_by": "2026-11-15T23:59:59.000Z",
"created_at": "2026-11-01T08:00:05.000Z",
"profile_id": "pro_demo_001",
"is_already_refunded": false
}
]Response
An array of dispute objects, with the same fields as Retrieve a dispute.
Accept a dispute
Accepts a dispute: you agree that the customer keeps the money and you will not challenge it. This cannot be undone. There is no request body.
POST /disputes/accept/{dispute_id}
Authentication: secret API key (api-key header).
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
dispute_id | string | Yes | The dispute to accept. |
You can accept a dispute only while its status is dispute_opened or dispute_challenged and
its stage is pre_dispute, dispute, pre_arbitration or arbitration. Otherwise VNSwitch
returns an error.
Do not also refund a payment whose dispute you accept or lose: the dispute already returns the
money to the customer. Check is_already_refunded before any manual refund.
Example request
Response
{
"dispute_id": "dp_4a9f2c7e1b",
"payment_id": "pay_8f2c1d9e0a",
"attempt_id": "pay_8f2c1d9e0a_1",
"amount": "150000",
"currency": "VND",
"dispute_stage": "dispute",
"dispute_status": "dispute_accepted",
"connector": "<PROVIDER>",
"connector_status": "accepted",
"connector_dispute_id": "<PROVIDER_DISPUTE_ID>",
"connector_reason": "Product not received",
"challenge_required_by": "2026-11-15T23:59:59.000Z",
"created_at": "2026-11-01T08:00:05.000Z",
"profile_id": "pro_demo_001",
"is_already_refunded": false
}Response
The dispute object, normally with dispute_status dispute_accepted.
Retrieve dispute evidence
Lists the evidence files attached to a dispute. Evidence is uploaded in the VNSwitch dashboard; use this operation to check from your systems what has been attached.
GET /disputes/evidence/{dispute_id}
Authentication: secret API key (api-key header).
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
dispute_id | string | Yes | The dispute ID. |
Example request
Response
[
{
"evidence_type": "receipt",
"file_metadata_response": {
"file_id": "file_9d3b6a2c1e",
"file_name": "receipt-ORD-1001.pdf",
"file_size": 48213,
"file_type": "application/pdf",
"available": true
}
},
{
"evidence_type": "shipping_documentation",
"file_metadata_response": {
"file_id": "file_2e8c5f7a4b",
"file_name": "delivery-proof.jpg",
"file_size": 215004,
"file_type": "image/jpeg",
"available": true
}
}
]Response
An array of evidence blocks:
| Field | Description |
|---|---|
evidence_type | What the file proves: receipt, invoice_showing_distinct_transactions, customer_communication, customer_signature, shipping_documentation, service_documentation, refund_policy, cancellation_policy, recurring_transaction_agreement or uncategorized_file. |
file_metadata_response.file_id | The file ID. |
file_metadata_response.file_name | The file name. |
file_metadata_response.file_size | Size in bytes. |
file_metadata_response.file_type | The file’s media type. |
file_metadata_response.available | true when the file has been stored and can be used. |