Skip to main content

Item Add Webhook

Aghanim offers a centralized webhook that alerts your game to credit items to a player's account based on their activities within the game hub. This webhook is triggered whenever a player takes an action that requires item crediting. This guide provides detailed insights into the functionality and setup of this webhook.

This webhook is triggered in the following cases:

  • A player makes a purchase on the game hub
  • A player redeems a free item code on the game hub
  • A player claims a daily reward or loyalty program reward

Each alert includes a reason field with the justification for item crediting.

Redeem code webhook image
Redeem code webhook image

Requirements

To use the item.add 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_key included in the webhook payload to prevent processing duplicate webhooks.
  • Credit the specified item to a player's account.
  • Respond with 2xx status codes to signal successful processing, and 4xx or 5xx for denial or errors.

Configuration

Below are function templates for an endpoint that processes Aghanim webhooks, alerting your game to credit items:

import fastapi, hashlib, hmac, json, typing 

app = fastapi.FastAPI()

@app.post("/webhook")
async def webhook(request: fastapi.Request) -> dict[str, typing.Any]:
secret_key = "<YOUR_S2S_KEY>" # Replace with your actual webhook secret key

raw_payload = await request.body()
payload = raw_payload.decode()
timestamp = request.headers["x-aghanim-signature-timestamp"]
received_signature = request.headers["x-aghanim-signature"]

if not verify_signature(secret_key, payload, timestamp, received_signature):
raise fastapi.HTTPException(status_code=403, detail="Invalid signature")

data = json.loads(payload)
event_type = data["event_type"]
event_data = data["event_data"]

if event_type == "item.add":
add_item(event_data)
return {"status": "ok"}

raise fastapi.HTTPException(status_code=400, detail="Unknown event type")

def verify_signature(secret_key: str, payload: str, timestamp: str, received_signature: str) -> bool:
signature_data = f"{timestamp}.{payload}"
computed_hash = hmac.new(secret_key.encode(), signature_data.encode(), hashlib.sha256)
computed_signature = computed_hash.hexdigest()
return hmac.compare_digest(computed_signature, received_signature)

def add_item(event_data: dict[str, typing.Any]) -> None:
# Placeholder logic for processing the event and adding item.
# In a real application, this function would interact with your database or inventory system.
player_id = event_data["player_id"]
for item in event_data["items"]:
sku = event_data["sku"]
print(f"Item {sku} have been credited to player's {player_id} account.")

Once your function is ready:

  1. Make your endpoint available.
  2. Register your endpoint within Aghanim account → GameWebhooksNew Webhook by choosing the corresponding event type.

Alternatively, you can register your endpoint within Aghanim using the Create Webhook API method.

Request schema

Below is an example of an item.add webhook request:

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": "item.add",
"event_data": {
"player_id": "2D2R-OP3C",
"items": [
{
"id": "itm_exTBZQmIlDz",
"name": "Crystals",
"description": "Reign supreme over your rivals with this massive crystal treasure.",
"sku": "crystals",
"quantity": 480000,
"price": 9499,
"price_decimal": 94.99,
"currency": "USD",
"type": "item",
"nested_items": null,
"fallback_item": null
}
],
"reason": "Order paid ord_eCacAulggpY"
},
"event_time": 1725548450,
"event_id": "whevt_eCacGbJVbvToOgzjXUgOCitkQE",
"idempotency_key": "idmpt_aXRlb...JkX2VFS",
"request_id": "d1593e9c-c291-4004-8846-6679c2e5810b",
"sandbox": false,
"trigger": "order.paid",
"transaction_id": "whtx_eCacGbJVbvT",
"context": {
"order": {
"id": "ord_eCacAulggpY",
"amount": 9499,
"country": "US",
"currency": "USD",
"revenue_usd": 9499,
"fees": {
"payment_system_fee_usd": 2.85,
"aghanim_fee_usd": 14.25,
"taxes_usd": 7.65
},
"receipt_number": "1234567890",
"status": "paid",
"created_at": 1725548450,
"paid_at": 1725548460,
"creator": null
}
},
"game_id": "gm_exTAyxPsVwh"
}

The Event schema

KeyTypeDescription
event_idstringUnique Event ID generated by Aghanim.
game_idstringYour game ID in the Aghanim system.
event_typestringThe type of the event, item.add in this case.
event_timenumberEvent date in Unix epoch time.
event_dataEventDataContains the event-specific data, with possible keys for inherited objects.
idempotency_keystringEnsures webhook actions are executed only once, even if retried.
request_idstring|nullIf the event was triggered by an API request, the request ID is included.
sandboxbooleanIndicates whether the event was sent from the sandbox game environment.
triggerstring|nullThe trigger that caused the event to be sent.
transaction_idstringThe transaction ID generated by Aghanim. This ID may be the same for multiple events emitted within the same transaction.
contextEventContext|nullContextual information about the event.

The EventContext schema

KeyTypeDescription
orderOrderContext|nullOrder information associated with the event if applicable.
playerPlayerContext|null(Optional) Player information. To add this, enable "Add player context" in the webhook settings.

The EventData schema

KeyTypeDescription
player_idstringThe unique Player ID chosen for player authentication.
itemsItem[]An array of items to be credited to the player's account.
reasonstringThe human-readable reason that triggered the webhook. Example: Order paid ord_eCacAulggpY.

The Trigger values

ValueDescription
coupon.redeemedWhen a coupon for a free item is redeemed.
order.paidWhen a purchase is completed successfully.
hub.free_item_claimWhen the player claims a free item in the store.
hub.daily_reward_claimWhen the player collects a reward for a daily reward program.
hub.loyalty_claimWhen the player collects a loyalty program reward.
hub.progression_reward_claimedWhen the player collects a progression reward.
hub.rolling_offer_claimedWhen the player claims reward in rolling offer.
hub.pick_one_offer_claimedWhen the player claims reward in pick one offer.
hub.lootbox.openWhen the player opens a lootbox after purchase.
testWhen using the "Send test event" in the Dashboard.

The Item schema

KeyTypeDescription
idstringItem ID generated by Aghanim.
namestringItem name.
descriptionstring|nullItem description.
skustringItem SKU matching on both the game and Aghanim sides.
quantitynumberItem quantity.
pricenumber|nullItem price in minor currency units. If the item is free, this field is null.
price_decimalnumber|nullItem price in decimal units. If the item is free, this field is null.
currencystring|nullItem price currency. If the item is free, this field is null.
typestringThe type of item. Possible values: item, bundle.
nested_itemsNestedItem[]|nullAn array of items included in the bundle.
fallback_itemItem|nullThe item that may be given as fallback if the main item can't be given to the player.

Item type bundle can contain several nested items inside.
You can handle the common sku of the bundle or handle each nested item individually.

The NestedItem schema

KeyTypeDescription
idstringItem ID generated by Aghanim.
namestringItem name.
descriptionstring|nullItem description.
skustringItem SKU matching on both the game and Aghanim sides.
quantitynumberItem quantity.
typestringThe type of item. Possible values: item, bundle.
nested_itemsNestedItem[]|nullAn array of items included in the bundle.

The OrderContext schema

KeyTypeDescription
idstringUnique Order ID generated by Aghanim.
receipt_numberstringReceipt number shown to the player in their receipt.
amountnumberOrder amount in local currency, in minor currency units.
amount_before_discountnumberOrder amount before discount in local currency, in minor currency units.
payment_amountnumberFinal amount charged to the customer in local currency, including taxes, in minor currency units.
currencystringThree-letter currency code (ISO 4217) of the order.
payment_methodstringThe payment method used, for example card, apple_pay, google_pay, paypal.
countrystringTwo-letter country code (ISO 3166-1 alpha-2) of the payment method country.
payment_amount_usdnumberThe payment amount converted to USD (e.g., 112.50 for $112.50) using estimated foreign exchange rates. The final value is confirmed after reconciliation with payment providers, typically by the 10th of the following month.
revenue_usdnumberThe expected net revenue, converted to USD cents using estimated foreign exchange rates and payment method fees. The final value is determined after reconciliation with payment providers, typically by the 10th of the following month.
feesFees|nullInformation about taxes and fees. The final values are determined after reconciliation with payment providers, typically by the 10th of the following month.
statusstringOrder status. Can be: created, captured, paid, canceled, refunded, refund_requested.
sales_channelstringIndicates the sales channel. Can be: game_hub, checkout, android_sdk, checkout_link.
eligible_for_reward_pointsnumber|nullThe number of reward points the order is eligible for.
eligible_for_loyalty_pointsnumber|nullThe number of loyalty points the order is eligible for.
created_atnumberOrder creation date in Unix epoch time.
paid_atnumber|nullOrder payment date in Unix epoch time.
creatorCreator|nullInformation about creator associated with the order.
metadataobject|nullThe metadata object structured as key-value pairs to store additional information about the order.

The Fees schema

KeyTypeDescription
payment_system_fee_usdnumber|nullPayment processing fee in USD cents.
aghanim_fee_usdnumber|nullAghanim platform fee in USD cents.
taxes_usdnumber|nullTaxes in USD cents.

The Creator schema

KeyTypeDescription
namestringName of the creator.
payout_decimal_usdnumberCreator payout amount in USD in major units.

The PlayerContext schema

KeyTypeDescription
player_idstring|nullThe unique Player ID chosen for player authentication.
playerobject|nullPlayer ID components when using Composite Authorization.
attributesAttributesBasic player attributes expected by Aghanim.
custom_attributesCustomAttributesCustom player attributes.

Optional: Rejecting purchases with automatic refunds

In some cases, your game server may need to reject a purchase after payment has been processed - for example, when a promotion has expired or a player doesn't meet purchase requirements. Aghanim supports automatic refund processing for these scenarios.

To reject a purchase, respond with a 400 status code:

{
"status": "error",
"code": "declined",
"message": "Purchase rejected: promotion has expired"
}
info

Automatic refunds must be configured by the Aghanim team. Please contact our integration team to enable automatic refunds for purchases rejected with code="declined".

For detailed information about implementing automatic refunds, including error codes, see Automatic Payment Refunds.

Need help?
Contact our integration team at integration@aghanim.com