How Evaluations Work
The Evaluation API takes a dispute case and returns:
- The category Triple classified the case as
- A confidence score
- A proposed card-network reason code
- The specific gaps that weaken the case before submission to the scheme
Classification is part of the evaluation. You don't send a category and you don't need to map your own reason codes to Triple's categories. Triple classifies the case from the evidence and returns the resulting category on the result.
If the cardholder hasn't yet described the dispute in structured form, use our hosted intake instead of calling this endpoint directly. Triple collects the statement, runs the evaluation (including classification), and hands you back the result.
What the evaluator takes in
A case is built from four things, however you provide them:
dispute: the disputed amount and currencytransaction: the original charge being disputedcard: the card snapshotevidences: cardholder statement and any supporting evidence
You don't send a category. Triple classifies the case from the inputs above as the first step of the evaluation.
How classification works
Classification runs as the first step of every evaluation. It uses:
- The cardholder statement and any supporting evidence in
evidences - Transaction signals like channel, AVS, CVV, and merchant category code
- Card signals like chip and PIN capability
- The dispute amount relative to the transaction amount
The classifier picks one of the supported categories. The chosen category drives which evidence the rest of the evaluation expects and which card-network reason codes can be proposed. The final category appears on the result as category.
Supported categories
| Category | When it applies |
|---|---|
fraud | The cardholder did not authorize the transaction |
service_not_received | Goods or services paid for but not delivered |
processing_duplicate | The same transaction was charged more than once |
cancelled | The cardholder cancelled and the merchant didn't refund, retained fees, or mismatched their own policy |
Additional categories will come online over time without any integration changes on your side.
Evaluation flow
When you submit a case for evaluation, the API returns an evaluation ID immediately. The evaluation is then processed asynchronously, and once it finishes, the result is available to retrieve. The recommended way to know when a result is ready is by configuring a webhook.
1. Submit a case
curl -X POST https://api.disputes.sandbox.tripledev.app/api/evaluations/ \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"dispute": {
"disputed_amount": 299.99,
"disputed_currency": "USD"
},
"transaction": {
"transaction_id": "txn_12345",
"card_scheme": "MC",
"channel_type": "ECOMMERCE",
"merchant_name": "ACME Store",
"merchant_country": "USA",
"transaction_amount": 299.99,
"transaction_currency": "USD",
"merchant_id": "MERCHANT123",
"transaction_timestamp": "2024-01-20T10:30:00Z",
"settlement_timestamp": "2024-01-22T00:00:00Z",
"arn": "12345678901234567890123",
"rrn": "123456789012",
"merchant_category_code": "5311",
"terminal_id": "term_01",
"mobile_wallet": null,
"avs_result": "NO_MATCH",
"cvv_match": false,
"eci_code": "05",
"batch_id": "batch_001"
},
"card": {
"bin": "54133388",
"last_4": "1234",
"emv_chip_enabled": true,
"emv_pin_preferring": false
},
"evidences": {
"cardholder_statement": "I did not make this purchase. My card details were stolen..."
}
}'
2. Store the evaluation ID
The API immediately returns an evaluation ID. You must store this ID to retrieve the result later.
{
"id": "550e8400-e29b-41d4-a716-446655440000"
}
The evaluation process is asynchronous. Store the id value. You will need it to retrieve the evaluation result.
3. Receive the evaluation result
Once processing is complete, you can receive the result in two ways.
Webhooks (recommended)
Configure a webhook endpoint to receive results automatically as soon as the evaluation is ready. This is the recommended approach for production integrations.
See Webhooks Guide for setup instructions.
Fallback: polling
If you cannot use webhooks, you can poll the result endpoint using the evaluation ID. Since evaluations are processed asynchronously, you will need to define a polling strategy to periodically check for results. Webhooks avoid this by delivering results to your server as soon as they are ready.
curl https://api.disputes.sandbox.tripledev.app/api/evaluations/{evaluation_id}/result \
-H "Authorization: Bearer $API_KEY"
Understanding the result
The evaluation result contains the final category, the confidence level, the proposed reason code, and any failed checks:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"category": "fraud",
"confidence": "high",
"reason_code": "4837",
"failed_checks": []
}
Category
The category Triple classified the case as.
Confidence
The confidence level indicates the strength of the dispute case:
| Level | Description |
|---|---|
high | Strong case with sufficient evidence |
moderate_high | Good case, minor improvements possible |
moderate_low | Moderate case, may benefit from additional evidence |
low | Weak case, significant issues identified |
Reason code
We return reason_code when the system is able to classify the dispute precisely enough to determine a card-network reason code. If the available information is not sufficient for a precise classification, reason_code is null and the failed checks will highlight the additional information needed.
Failed checks
The failed_checks array uses a format similar to Pydantic validation errors. Each entry identifies a specific issue:
{
"id": "6c825d27-db81-4f60-8f7c-2d87ac0b71a1",
"confidence": "low",
"failed_checks": [
{
"loc": [
"body",
"payload",
"fraud",
"evidences",
"cardholder_statement"
],
"msg": "No meaningful purchase details were provided. Without basic context, the dispute shouldn't be raised.",
"type": "error"
},
{
"loc": [
"body",
"payload",
"fraud",
"evidences",
"expected_at"
],
"msg": "The expected delivery or service date has not yet passed. The merchant may still be within their fulfilment window.",
"type": "error"
}
]
}
Each failed check contains:
| Field | Description |
|---|---|
loc | Path to the field, for example ["body", "payload", "fraud", "evidences", "cardholder_statement"] |
msg | Description of the issue |
type | Either error (validation issue) or missing_info (recommended evidence) |
Use failed checks to understand why a dispute received a lower confidence score, what additional information is missing, and what might improve it.
Validation errors
If your request has validation issues, the API returns a 422 response with Pydantic-style errors:
{
"detail": [
{
"loc": ["body", "payload", "fraud", "dispute", "disputed_amount"],
"msg": "Input should be greater than 0",
"type": "greater_than"
},
{
"loc": ["body", "payload", "fraud", "evidences", "cardholder_statement"],
"msg": "String should have at least 35 characters",
"type": "string_too_short"
}
]
}
Next steps
- Set up webhooks to receive results as soon as they are ready
- Learn about the Evaluation Payload structure