Payment Webhooks
When a player attempts to pay for an order, a payment is created. Aghanim's payment events webhook notifies your game of any status changes for payments linked to the order, providing detailed information across all possible states for analytics and tracking.
This webhook is activated through the Payment events event, selectable in Game → Webhooks.
A single order can be associated with multiple payments if the player made multiple attempts to pay that either failed or were not completed.
Payment events may be sent multiple times for the same payment ID when payment details (amounts, commissions, taxes) are updated after the initial event. This can happen even if the payment status remains the same, as these updates affect revenue tracking and analytics.
When handling payment events:
- Use the
idempotency_keyto identify duplicate events - Either ignore duplicate events or update your records with the latest payment information
- Do not raise errors for duplicate events, as this will trigger webhook retries based on the retry schedule
- Note that multiple payment attempts for the same order will have different payment IDs (
idfield), not duplicate events
Payment Statuses
The payment webhook can be triggered for any of the following payment statuses:
succeeded– The payment was successfully completed and the funds were deducted from the user's accountcanceled– The payment was canceled by the user during the checkout processchargeback– The payment was canceled due to a chargeback requestdeclined– The payment could not be completed because the user's payment method was declineddispute– The user filed a dispute with their payment method regarding this paymentexpired– The payment expired because it wasn't completed in timepending– The payment was initiated by the user and is pending completionrefunded– The payment was refunded and the funds returned to the userrejected– The payment was flagged as potentially fraudulent and was not processedvoided– The payment was voided before any funds were transferred
Requirements
To use the payment events webhook from Aghanim, you should have the webhook server configured as follows:
- HTTPS endpoint, accepting POST webhook requests.
- Listen for events, generated and signed by Aghanim.
- Handle the
idempotency_keyincluded in the webhook payload to prevent processing duplicate webhooks. - Respond with 2xx status codes if the payment event was processed successfully, and 4xx or 5xx for denial or errors.
Configuration
- Develop a function for the
payment.*webhook processing. - Make your endpoint available.
- Register your endpoint within Aghanim account → Game → Webhooks → New Webhook by choosing the payment events event type.
Alternatively, you can register your endpoint within Aghanim using the Create Webhook API method.
Request schema
Below is an example of an payment.succeeded webhook request:
- HTTP
- cURL
POST /your/webhook/uri HTTP/1.1
Content-Type: application/json
Host: your-webhook-endpoint.com
User-Agent: Aghanim/0.1.0
X-Aghanim-Signature: 2e45ed4dede5e09506717490655d2f78e96d4261040ef48cc623a780bda38812
X-Aghanim-Signature-Timestamp: 1725548450
{
"event_type": "payment.succeeded",
"event_data": {
"id": "pmt_eFgYpxryeKXpLKfmZstI",
"order_id": "ord_eCacpFwavzi",
"receipt_number": "2409051289614565",
"status": "succeeded",
"amount": 9499,
"currency": "USD",
"payment_method": "cards",
"created_at": 1725547595,
"modified_at": 1725547657,
"metadata": null,
"decline_reason_code": null,
"decline_reason": null,
"three_d_secure_result": "authenticated",
"three_d_secure_flow": "challenge"
},
"event_time": 1725548450,
"event_id": "whevt_eCacGbJVbvToOgzjXUgOCitkQE",
"idempotency_key": "idmpt_aXRlb...JkX2VFS",
"request_id": "d1593e9c-c291-4004-8846-6679c2e5810b",
"sandbox": false,
"trigger": "checkout.purchase",
"transaction_id": "whtx_eCacGbJVbvT",
"context": null,
"game_id": "gm_exTAyxPsVwh"
}
curl "https://your-webhook-endpoint.com/your/webhook/uri" \
-X POST \
-H "Content-Type: application/json" \
-H "User-Agent: Aghanim/0.1.0" \
-H "X-Aghanim-Signature: 2e45ed4dede5e09506717490655d2f78e96d4261040ef48cc623a780bda38812" \
-H "X-Aghanim-Signature-Timestamp: 1725548450" \
-d '{
"event_type": "payment.succeeded",
"event_data": {
"id": "pmt_eFgYpxryeKXpLKfmZstI",
"order_id": "ord_eCacpFwavzi",
"receipt_number": "2409051289614565",
"status": "succeeded",
"amount": 9499,
"currency": "USD",
"payment_method": "cards",
"created_at": 1725547595,
"modified_at": 1725547657,
"metadata": null,
"decline_reason_code": null,
"decline_reason": null,
"three_d_secure_result": "authenticated",
"three_d_secure_flow": "challenge"
},
"event_time": 1725548450,
"event_id": "whevt_eCacGbJVbvToOgzjXUgOCitkQE",
"idempotency_key": "idmpt_aXRlb...JkX2VFS",
"request_id": "d1593e9c-c291-4004-8846-6679c2e5810b",
"sandbox": false,
"trigger": "checkout.purchase",
"transaction_id": "whtx_eCacGbJVbvT",
"context": null,
"game_id": "gm_exTAyxPsVwh"
}'
The Event schema
| Key | Type | Description |
|---|---|---|
event_id | string | Unique Event ID generated by Aghanim. |
game_id | string | Your game ID in the Aghanim system. |
event_type | string | The type of the event, payment.succeeded in this case. |
event_time | number | Event date in Unix epoch time. |
event_data | EventData | Contains the event-specific data, with possible keys for inherited objects. |
idempotency_key | string | Ensures webhook actions are executed only once, even if retried. |
request_id | string|null | If the event was triggered by an API request, the request ID is included. |
sandbox | boolean | Indicates whether the event was sent from the sandbox game environment. |
trigger | string|null | The trigger that caused the event to be sent. |
transaction_id | string | The transaction ID generated by Aghanim. This ID may be the same for multiple events emitted within the same transaction. |
context | object|null | Contextual information about the event. |
The EventData schema
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier for the payment |
order_id | string | Unique identifier for the associated order |
receipt_number | string | Human-readable receipt number |
status | enum | Current payment status (succeeded, canceled, chargeback, declined, dispute, expired, pending, refunded, rejected, voided) |
amount | number | Payment amount in minor currency units |
currency | string | Payment currency |
payment_method | string | Payment method used (cards, apple_pay, google_pay, paypal, etc.) |
created_at | integer | Unix timestamp when the payment was created |
modified_at | integer | Unix timestamp when the payment was last modified |
metadata | object|null | The metadata object structured as key-value pairs to store additional information about the payment. |
decline_reason | string|null | Human-readable description of the payment decline |
decline_reason_code | string|null | Alphanumeric decline code identifying the decline reason |
three_d_secure_result | string|null | 3DS authentication result (not_attempted, authenticated, failed) |
three_d_secure_flow | string|null | 3DS authentication flow used during the payment attempt (none, challenge, frictionless) |
Event Types
The webhook will be triggered for the following event types based on payment status changes:
payment.succeededpayment.canceledpayment.chargebackpayment.declinedpayment.disputepayment.expiredpayment.pendingpayment.refundedpayment.rejectedpayment.voided
Need help?
Contact our integration team at integration@aghanim.com