Payment Dispute Evidence
When a player disputes a payment, the payment processor asks Aghanim to prove that the purchase was legitimate and delivered. Aghanim compiles an evidence package from the data it already has, and the S2S Dispute Evidence API lets your game server add the game-side facts the platform cannot know: whether the purchased goods were consumed, where they were used, and details about the player's account in the game.
How it works
- Dispute opened - A player files a dispute with their payment method. Aghanim sends a
payment.disputewebhook for the payment. - You submit evidence - Your server calls the Dispute Evidence API with consumption facts, player details, and supporting files.
- Evidence package sent - Aghanim includes your evidence in the package submitted to the payment processor.
- Dispute resolved - The outcome arrives as a
payment.succeeded(won) orpayment.chargeback(lost) webhook carrying thedisputeobject.
Prerequisites
- API Key: Required for authenticating your S2S API requests.
- Payment number: The endpoints identify the payment by its payment number, which is the
receipt_numberfield of the payment webhook payload.
Submit evidence
Create or update dispute evidence for a payment:
PUT https://api.aghanim.com/s2s/v1/payments/{payment_number}/dispute_evidence
Request schema
All fields are optional. The request is a partial update: only the fields present in the JSON body are written, fields you omit keep their stored values, and a field sent as null is cleared. Repeated calls merge into the same evidence record.
| Field | Type | Description | Required |
|---|---|---|---|
purchase_used | boolean | Whether the purchased goods were consumed. | No |
used_at | number | Unix timestamp when the purchased goods were consumed. | No |
usage_id | string | Your identifier of the event where the goods were consumed, e.g. a match, session, or quest ID. Max 512 characters. | No |
comment | string | Free-form note for support. Max 4096 characters. | No |
player_attributes | PlayerAttributes | Player fields stored on the player profile, not on the payment. | No |
The PlayerAttributes object schema
| Field | Type | Description | Required |
|---|---|---|---|
registered_at | number | Unix timestamp when the player registered in the game. It may predate the creation of the player's Aghanim account. | No |
first_login_ip | string | IP address of the player's first login in the game, as reported by the game. Max 64 characters. | No |
is_verified | boolean | Whether the player's account is verified on the game side. | No |
The player_attributes fields are the same attributes your server can return from the player.verify webhook; use whichever channel fits your integration.
Example request
curl -X PUT https://api.aghanim.com/s2s/v1/payments/2409051289614565/dispute_evidence \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <YOUR_API_KEY>' \
-d '{
"purchase_used": true,
"used_at": 1725634567,
"usage_id": "match_8f3a1c",
"comment": "Crystals were spent on a legendary chest",
"player_attributes": {
"registered_at": 1609459200,
"first_login_ip": "203.0.113.7",
"is_verified": true
}
}'
The response is the DisputeEvidence object.
Retrieve evidence
Return the stored dispute evidence for a payment, including the player fields:
GET https://api.aghanim.com/s2s/v1/payments/{payment_number}/dispute_evidence
The response is the DisputeEvidence object. The endpoint responds with 404 when no evidence has been submitted for the payment yet.
Upload an evidence file
Attach a supporting file (a screenshot, a log extract, a receipt) to the payment's evidence:
POST https://api.aghanim.com/s2s/v1/payments/{payment_number}/dispute_evidence/files
Request schema
The file is sent as base64 inside a JSON body, not as multipart form data:
| Field | Type | Description | Required |
|---|---|---|---|
file_name | string | Original file name, kept as part of the stored file ID. Max 255 characters. | Yes |
file_type | string | MIME type of the file, e.g. application/pdf. Defaults to application/octet-stream. | No |
file_base64_content | string | File content encoded as base64. Up to roughly 10 MB of binary data. | Yes |
The content must be valid base64 without line breaks or whitespace, otherwise the request fails with 422.
Example request
curl -X POST https://api.aghanim.com/s2s/v1/payments/2409051289614565/dispute_evidence/files \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <YOUR_API_KEY>' \
-d '{
"file_name": "consumption-log.pdf",
"file_type": "application/pdf",
"file_base64_content": "JVBERi0xLjQKJ..."
}'
The endpoint responds with 201 and the DisputeEvidence object including the updated file_ids. Each upload appends to the list; there is no way to remove an uploaded file via the API, so contact support if a file was attached by mistake.
The DisputeEvidence object
Both endpoints and the file upload return the full evidence record:
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier of the evidence record, prefixed with pde_. |
payment_number | string | Payment number the evidence belongs to. |
purchase_used | boolean|null | Whether the purchased goods were consumed. |
used_at | number|null | Unix timestamp when the purchased goods were consumed. |
usage_id | string|null | Your identifier of the event where the goods were consumed. |
file_ids | string[]|null | Identifiers of the uploaded evidence files. |
comment | string|null | Free-form note for support. |
modified_at | number|null | Unix timestamp of the last update, null until the record is updated. |
player_attributes | PlayerAttributes | Player fields from the player profile; all fields are null when unknown. |
The PlayerAttributes object in responses
| Field | Type | Description |
|---|---|---|
registered_at | number|null | Unix timestamp when the player registered in the game. |
last_active_at | number|null | Unix timestamp of the player's last activity on the platform. Read-only. |
first_login_ip | string|null | IP address of the player's first login in the game. |
is_verified | boolean|null | Whether the player's account is verified on the game side. |
Example response
{
"id": "pde_eFgYpxryeKXpLKfmZstI",
"payment_number": "2409051289614565",
"purchase_used": true,
"used_at": 1725634567,
"usage_id": "match_8f3a1c",
"file_ids": ["fl_a1b2c3_consumption-log.pdf"],
"comment": "Crystals were spent on a legendary chest",
"modified_at": 1725638167,
"player_attributes": {
"registered_at": 1609459200,
"last_active_at": 1725630000,
"first_login_ip": "203.0.113.7",
"is_verified": true
}
}
Error responses
| HTTP Status | Endpoint | Description |
|---|---|---|
401 | All | Missing or invalid API key. |
404 | All | The payment number is unknown for your game. |
404 | GET | No dispute evidence has been submitted for the payment yet. |
404 | PUT | player_attributes fields were sent, but the payment has no player to store them on. |
422 | PUT, POST | Validation error: a field exceeds its length limit or file_base64_content is not valid base64. |
Need help?
Contact our integration team at [email protected]