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:

StageMeaning
pre_disputeAn early inquiry, before a formal dispute.
disputeA formal dispute (chargeback).
pre_arbitrationThe customer’s side has answered your challenge; you can respond once more.
arbitrationThe card scheme or bank decides the case.
dispute_reversalA dispute that was reversed.

dispute_status says what is happening now:

StatusMeaning
dispute_openedOpen and waiting for you to accept or challenge it.
dispute_challengedYou challenged it; waiting for the decision.
dispute_acceptedYou accepted it. Final.
dispute_wonDecided in your favour. Final.
dispute_lostDecided in the customer’s favour. Final.
dispute_expiredThe deadline passed without a response. Final.
dispute_cancelledThe 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

ParameterTypeRequiredDescription
dispute_idstringYesThe dispute ID, from the webhook or from List disputes.

Query parameters

ParameterTypeRequiredDescription
force_syncbooleanNotrue 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:

FieldDescription
dispute_idThe dispute ID.
payment_idThe disputed payment.
amount, currencyThe disputed amount (a string, in the minor unit) and its currency.
dispute_stage, dispute_statusSee Dispute stages and statuses.
connector_reason, connector_reason_codeThe reason given by the issuer or bank, as reported by the provider.
challenge_required_byDeadline for your challenge (ISO 8601). Can be null if the provider does not report one.
connector_statusThe provider’s own status text. Use dispute_status in your logic.
is_already_refundedtrue 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_atWhen 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

ParameterTypeRequiredDescription
dispute_statusstringNoOne or more statuses, comma-separated, for example dispute_opened,dispute_challenged.
dispute_stagestringNoOne or more stages, comma-separated, for example dispute,pre_arbitration.
payment_idstringNoOnly disputes of this payment.
reasonstringNoOnly disputes with this reason.
currencystringNoOne or more currency codes, comma-separated, for example VND.
start_timestringNoISO 8601 date-time. Only disputes received at or after this time.
end_timestringNoISO 8601 date-time. Only disputes received up to this time. Defaults to now. Use it together with start_time.
limitintegerNoNumber of disputes to return, 1 to 100. Default 10.
offsetintegerNoNumber 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

ParameterTypeRequiredDescription
dispute_idstringYesThe 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

ParameterTypeRequiredDescription
dispute_idstringYesThe 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:

FieldDescription
evidence_typeWhat 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_idThe file ID.
file_metadata_response.file_nameThe file name.
file_metadata_response.file_sizeSize in bytes.
file_metadata_response.file_typeThe file’s media type.
file_metadata_response.availabletrue when the file has been stored and can be used.