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), or13(consumer dispute).dispute_due_to= Pick best enum reason for dispute. Required ifmodality=12or13. Not necessary for10or11.first_installment_amount- Enter value for this field if the dispute has more than one installmentis_partial- Set totrueif 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 IDstatus.description- initial status -PENDINGstatus.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= stolenfraud_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:
PENDINGtoOPENED - group status:
OPENtoOPEN
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:
OPENEDtoCHARGEBACK_CREATED - group status:
OPENtoCARDNETWORK_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:
OPENEDtoFAILED - group status:
OPENtoFAILED
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_CREATEDtoCHARGEBACK_ACCEPTED - group status:
CARDNETWORK_CHARGEBACKtoWON
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_CREATEDtoSECOND_PRESENTMENT - group status:
CARDNETWORK_CHARGEBACKtoCARDNETWORK_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_CREATEDtoCHARGEBACK_CLOSED - group status:
CARDNETWORK_CHARGEBACKtoLOSS
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_PRESENTMENTtoPRE_ARBITRATION_OPENED - group status:
CARDNETWORK_SECOND_PRESENTMENTtoCARDNETWORK_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_OPENEDtoPRE_ARBITRATION_ACCEPTED - group status:
CARDNETWORK_PREARBITRATIONtoWON
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_OPENEDtoPRE_ARBITRATION_DECLINED - group status:
CARDNETWORK_PREARBITRATIONtoLOSS
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_CREATEDtoPRE_ARBITRATION_OPENED - group status:
CARDNETWORK_CHARGEBACKtoCARDNETWORK_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_OPENEDtoPRE_ARBITRATION_ACCEPTED - group status:
CARDNETWORK_PREARBITRATIONtoLOSS
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_OPENEDtoPRE_ARBITRATION_DECLINED - group status:
CARDNETWORK_PREARBITRATIONtoWON
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 |
|
| ||
Update dispute status called to open dispute with Visa |
|
|
| |
Dispute opened with Visa |
|
|
| |
Chargeback accepted. Issuer wins. |
|
|
|
Updated about 1 hour ago