Visa dispute use case

Visa fraud dispute (reason code 10)

Below is a detailed, real-world walkthrough of a Visa fraud dispute going through the full lifecycle on the Pismo platform, including every API call, state machine transition, and event generated. For more information, refer to Visa dispute resolution.

Scenario

Maria contacts her issuer's call center to report that her Visa credit card was used for a fraudulent online purchase of $250.00 USD at Shady_store.com that she did not authorize. The card was not present (CNP fraud).

The issuer investigates and decides to proceed with a chargeback.

Step 1: Create the dispute

Issuer calls Pismo's Create dispute endpoint:

POST /v1/networkauthorization-disputes

Request payload

curl --request POST 'https://api.pismo.io/v1/networkauthorization-disputes' \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "authorization_id": 14123,
    "account_id": 12314,
    "modality": 10,
    "amount": 250.00,
    "currency_code": "USD",
    "reason_code": 10,
     "dispute_modality": "Fraud",
    "fraud_type": "B"
    "comment": "Cardholder reported an unauthorized card-not-present purchase at Shady_store.com for USD 250.00.",
    "merchant_name": "Shady_store.com",
    "transaction_date": "2026-07-10",
    "card_present": false
}

Key fields

  • modality = Enter category, aka Reason: 10 (fraud - card not present), 11 (authorization), 12 (processing error), or 13 (consumer dispute).
  • dispute_due_to = Pick best enum reason for dispute. Required if modality = 12 or 13. Not necessary for 10 or 11.
  • first_installment_amount - Enter value for this field if the dispute has more than one installment
  • is_partial - Set to true if the dispute is for a partial transaction amount and not the full amount.
  • comment - Add explanation if dispute is partial and not full
Response payload
{
  "id": 48670,  // Dispute ID
  "authorization_id": 14123,
  "account_id": 12314,
  "airport_tax": false,
  "airport_tax_partial": false,
  "airport_tax_amount": null,
  "comment": "Cardholder reported an unauthorized card-not-present purchase.",
  "dispute_installment_id": 8675309,
  "reason": {
    "dispute_reason_id": 1,
    "description": "Fraudulent transaction - no cardholder authorization",
    "reason_code": 10,
    "type": "Visa"
  },
  "status": {
    "id": 316,
    "description": "PENDING", // Initial status
    "type": "PRIMITIVE_ON_US",
    "group": "OPEN"  // Initial group status
  },
  "protocol": "20251128111532456",
  "disputed_amount": 250.00,
  "created_at": "2026-03-26 12:48:01",
  "created_at_utc": "2026-03-26T12:48:01.532292494Z",
  "is_partial": false,
  "network_brand_type": "Visa",
  "transaction_date": "2026-07-10",
  "transaction_amount": 250.00,
  "currency_code": "USD"
}

Key fields

  • id - dispute ID
  • status.description - initial status - PENDING
  • status.group - initial group status - CREATED.

The Create dispute call generates a Dispute installment created event.

Generated Dispute installment created event
{
  "id": 1,
  "dispute_id": 48670,
  "installment": 1,
  "arn": "test-arn",
  "chargeback_id": null,
  "claim_id": null,
  "installment_disputed_amount": 250.0,
  "network_return_reason_code": null,
  "reason_code": 10,
  "network_return_reject_reason": null,
  "network_response_error": null,
  "is_first_installment": false,
  "network_return_reject_reason_code": null,
  "dispute_status": {
    "id": 4,
    "description": "OPENED",
    "type": "PRIMITIVE",
    "group": "OPEN"
  },
  "account_id": 12314,
  "authorization_id": 14123,
  "internal_transaction_id": 123456789,
  "tracking_id": "9cd6485a-5680-4df0-a1f1-507e21d3428c",
  "network_brand_type": "Visa",
  "fraud_type": "1",
  "document_indicator": false,
  "network_response": [],
  "network_response_amount": 250.0,
  "network_response_currency": "USD",
  "network_status": "Authorization Dispute - Accepted by Acq",
  "reversal_reason": null,
  "transaction_id": "TI:example-network-transaction-id"
}

Initial state machine:

  • dispute status: PENDING
  • group status: OPEN

Step 2: Create fraud report (Visa TC40)

Issuer calls Create fraud report endpoint. A Visa TC40 report is a fraud notification document generated when a cardholder reports an unauthorized or fraudulent transaction to their issuing bank.

Note: A fraud report is automatically generated for a Visa fraud dispute so calling this endpoint for our example is not necessary. A Fraud report created event is also automatically generated.

POST /v1/disputes/{disputeId}/fraud-report

Note that the dispute_id is in the path.

Request payload
curl --request POST 'https://sandbox.pismolabs.io/disputes/v2/fraud-report' \
  --header 'Authorization: Bearer <account_token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "report_type": "visa",
    "transaction_id": 1234567890,
    "report": {
      "fraud_type": "1",
      "fraud_type_category": "CARDTXN",
      "notification_cd": 1,
      "close_fraud_case_ind": false
    }
  }'

Key fields:

  • fraud_type - 1 = stolen
  • fraud_type_category - CARDTXN = Card transaction
Response payload
{
  "fraud_report_id": 10,
  "org_id": "TN-123xxxxxxxxxxxxxxxxx",
  "status": "PENDING",
  "network": "Visa",
  "report": {
    "close_fraud_case_ind": false,
    "fraud_type": "1",
    "fraud_type_category": "CARDTXN",
    "notification_cd": 1
  },
  "created_at": "2024-10-18T11:20:22.000Z",
  "network_authorization_id": 1234567890,
  "authorization_code": "F0JR9H",
  "transaction_id": 1234567890,
  "account_id": 12314,
  "card_id": 123456,
  "report_type": "visa"
}

This call generates a Fraud report created event.

Create fraud report generated event
{
  "org_id": "TN-123",
  "report_type": "visa",
  "report": {
    "fraud_type": "1",
    "fraud_type_category": "CARDTXN",
    "notification_cd": 1,
    "close_fraud_case_ind": false
  },
  "status": "PENDING",
  "network": "Visa",
  "fraud_report_id": 10,
  "dispute_id": 48670,
  "dispute_installment_id": 8675309,
  "account_id": 12314,
  "card_id": 123456,
  "customer_id": 89345,
  "network_authorization_id": 14123,
  "authorization_code": "A1B2C3",
  "created_at": "2024-10-01 13:19:28",
  "updated_at": null,
  "case_number": null,
  "fraud_report_network_id": null,
  "network_response": null
}

Step 3: Upload evidence file (optional)

Issuer decides to upload Maria's police report via the Upload evidence file endpoint as additional support for the dispute.

POST /v1/disputes/{disputeId}/file

Request payload
curl --request POST 'https://sandbox.pismolabs.io/disputes/v1/disputes/48670/file' \
  --header 'Authorization: Bearer <account-token>' \
  --form 'name=Police Report' \
  --form 'category=CARD' \
  --form 'file=@/path/to/police_report.pdf;type=application/pdf' \
  --form 'dispute_installment_id=8675309'
Response payload
{
  "id": 1,
  "org_id": "TN-123",
  "dispute_id": 48670,
  "dispute_installment_id": 8675309,
  "installment": 1,
  "path": "/path/of/directory/",
  "file_name": "police_report.pdf",
  "category": "CARD"
}

This call generates a Dispute file uploaded audit event.

Upload evidence file generated event
{
    "method": "POST",
    "uri": "/v1/disputes/{disputeId}/file",
    "email": "[email protected]",
    "object": {
        "dispute_id": 48670,
        "path": "path/to/file/",
        "file_name": "police_report.pdf",
        "category": "CARD",
        "created_at_utc": "2026-05-10 11:09:08",
        "dispute_file_id": 1,
        "file_extension": "pdf",
        "dispute_installment_id": 8675309,
        "status": "PENDING",
        "updated_at": "2026-05-20 13:05:07"
    }
}

Step 4: Open dispute and send to Visa

Issuer passes the OPEN event to initiate the chargeback with Visa via the Update dispute status endpoint.

POST /v1/disputes/{disputeId}/event

Note that the dispute's ID is passed in the endpoint path.

Request payload
curl --request POST \
     --url https://sandbox.pismolabs.io/disputes/v1/disputes/48670/event \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "event": "OPEN"
}
'
Response payload
{
  "id": 48670,
  "org_id": "TN-123xxxxxxxxx",
  "account_id": 12314,
  "authorization_id": 14123,
  "comment": "Cardholder reported an unauthorized card-not-present purchase at Shady_store.com for USD 250.00.",
  "dispute_reason": 10,
  "modality": 10,
  "dispute_status": "OPENED",
  "dispute_status_group": "OPEN",
  "timeline": {
    "data": "test"
  },
  "protocol": "20190321L123456"
}

Note that the dispute status is now OPENED and the dispute status group is OPEN.

This call generates a Dispute status changed event.

Update dispute status generated event
{
  "id": 184740,
  "dispute_id": 48670,
  "installment": 1,
  "arn": "05131054165000000048149",
  "chargeback_id": null,
  "claim_id": null,
  "installment_disputed_amount": 250.0,
  "network_return_reason_code": null,
  "reason_code": 10,
  "network_return_reject_reason": null,
  "network_response_error": null,
  "is_first_installment": true,
  "network_return_reject_reason_code": null,
  "dispute_status": {
    "id": 4,
    "description": "OPENED",
    "type": "PRIMITIVE",
    "group": "CREATED"
  },
  "chargeback_ref_num": null,
  "dispute_due_to": null,
  "dispute_form": null,
  "dispute_fraud_report": null,
  "fraud_type": null,
  "document_indicator": true,
  "network_response": [],
  "network_response_amount": null,
  "network_response_currency": null,
  "network_status": null,
  "reversal_reason": null,
  "account_id": 12314,
  "authorization_id": 14123,
  "internal_transaction_id": 987654321,
  "tracking_id": "9cd6485a-5680-4df0-a1f1-507e21d3428c",
  "network_brand_type": "Visa"
}

Event: Update dispute status called with event OPENDispute status changed event generated.

State machine transition:

  • dispute status: PENDINGto OPENED
  • group status: OPENto OPEN

Visa accepts or rejects chargeback

Visa processes the request and either accepts or rejects the requested chargeback.

Visa accepts chargeback

Visa processes the request and accepts the chargeback. At this point, the chargeback has been officially filed. The acquirer has been notified.

Event: Update dispute status called with event ISSUER WORKEDDispute status changed event generated.

State machine transition:

  • dispute status: OPENED to CHARGEBACK_CREATED
  • group status: OPEN toCARDNETWORK_CHARGEBACK

Visa rejects chargeback

Visa processes the request and rejects the chargeback. Issuer has the chance to correct what's wrong and re-submit.

Event: Update dispute status called with event FAILED_ON_CREATIONDispute status changed event generated.

State machine transition:

  • dispute status: OPENED to FAILED
  • group status: OPEN toFAILED

Dispute resolution

A number of different scenarios can occur at this point.

Chargeback accepted (dispute closed - Issuer wins)

The acquirer does not contest the dispute. Visa notifies Pismo that the dispute is resolved. The $250.00 is returned to the issuer/cardholder through Visa's network settlement process.

Event: Update dispute status called with event CLOSEDDispute status changed event generated.

State machine transition:

  • dispute status: CHARGEBACK_CREATEDto CHARGEBACK_ACCEPTED
  • group status: CARDNETWORK_CHARGEBACK to WON

Second presentment

In a second presentment the merchant's acquiring bank resubmits the transaction with new evidence (e.g., signed receipts, proof of delivery) to prove the charge is valid.

Note: For a Visa fraud dispute, the second presentment is skipped and goes straight to pre-arbitration .

Acquirer contests dispute (second presentment)

The acquirer rejects chargeback and escalates dispute to second presentment

Event: Update dispute status called with event ISSUER_REPRESENTMENT_UNWORKEDDispute status changed event generated.

State machine transition:

  • dispute status: CHARGEBACK_CREATEDto SECOND_PRESENTMENT
  • group status: CARDNETWORK_CHARGEBACK to CARDNETWORK_SECOND_PRESENTMENT

Issuer accepts second presentment (dispute closed - Acquirer wins)

Issuer reviews the acquirer's evidence and agrees.

Event: Update dispute status called with event CLOSED_PROCESSED Dispute status changed event generated.

  • dispute status: CHARGEBACK_CREATEDto CHARGEBACK_CLOSED
  • group status: CARDNETWORK_CHARGEBACK to LOSS

Issuer rejects second presentment (pre-arbitration)

Issuer reviews the acquirer's evidence and still disagrees. The dispute is escalated to pre-arbitration.

Event: Update dispute status called with event SEND_PRE_ARBITRATION Dispute status changed event generated.

State machine transition:

  • dispute status: SECOND_PRESENTMENTto PRE_ARBITRATION_OPENED
  • group status: CARDNETWORK_SECOND_PRESENTMENT to CARDNETWORK_PREARBITRATION

Pre-arbitration

In a pre-arbitration, the Issuer has rejected the acquirer's second presentment.

Pre-arbitration accepted (dispute closed - Issuer wins)

Visa reviews and the acquirer accepts the pre-arbitration.

Event: Update dispute status called with event ACCEPT_PRE_ARBITRATION Dispute status changed event generated.

State machine transition:

  • dispute status: PRE_ARBITRATION_OPENEDto PRE_ARBITRATION_ACCEPTED
  • group status: CARDNETWORK_PREARBITRATION to WON

Pre-arbitration rejected (dispute closed - Acquirer wins)

Visa reviews and decides the acquirer is right.

Event: Update dispute status called with event DECLINE_PRE_ARBITRATION Dispute status changed event generated.

State machine transition:

  • dispute status: PRE_ARBITRATION_OPENEDto PRE_ARBITRATION_DECLINED
  • group status: CARDNETWORK_PREARBITRATION to LOSS

Acquirer skips second presentment

This is specific to Visa disputes where the acquirer initiates a pre-arbitration directly from CHARGEBACK_CREATED (skipping second presentment).

Acquirer initiates pre-arbitration

Acquirer skips second presentment and goes directly to pre-arbitration reviews.

Event: Update dispute status called with event SEND_PRE_ARBITRATION Dispute status changed event generated.

State machine transition:

  • dispute status: CHARGEBACK_CREATEDto PRE_ARBITRATION_OPENED
  • group status: CARDNETWORK_CHARGEBACK to CARDNETWORK_PREARBITRATION

Pre-arbitration accepted (dispute closed - Acquirer wins)

Visa reviews and the Issuer accepts the pre-arbitration.

Event: Update dispute status called with event ACCEPT_PRE_ARBITRATION Dispute status changed event generated.

State machine transition:

  • dispute status: PRE_ARBITRATION_OPENEDto PRE_ARBITRATION_ACCEPTED
  • group status: CARDNETWORK_PREARBITRATION to LOSS

Pre-arbitration rejected (dispute closed - Issuer wins)

Visa reviews and decides the Issuer is right.

Event: Update dispute status called with event DECLINE_PRE_ARBITRATION Dispute status changed event generated.

State machine transition:

  • dispute status: PRE_ARBITRATION_OPENEDto PRE_ARBITRATION_DECLINED
  • group status: CARDNETWORK_PREARBITRATION to WON

Pre-arbitration fails

If pre-arbitration fails—meaning the issuing bank and merchant cannot reach an agreement—the dispute is escalated to formal Visa Arbitration. Visa will review the case files and make a binding final ruling.The losing party of this final decision is typically responsible for hefty network arbitration filing fees, which can exceed $500 per transaction

Simple fraud use case progression

The following table details actions, events, and status changes in a simple fraud use case.


Action

Event

Dispute Status

Group Status

Pismo Event

Create dispute called


PENDING

OPEN

Dispute installment created

Update dispute status called to open dispute with Visa

OPEN

OPENED

OPEN

Dispute status changed

Dispute opened with Visa

ISSUER_WORKED

CHARGEBACK_CREATED

CARDNETWORK_CHARGEBACK

Dispute status changed

Chargeback accepted. Issuer wins.

CLOSED

CARDNETWORK_ACCEPTED

WON

Dispute status changed



Did this page help you?