Skip to main content

Player Verify Webhook

Aghanim utilizes a player verification webhook to inform your game about player logins, requiring confirmation from your webhook server to permit or deny access to the game hub. This document details the operation of these webhooks.

The webhook verifies a player's registration in your game and may be invoked multiple times during the player interactions with the game hub.

Verify player flow image
Verify player flow image

Requirements

To use the player verification webhook from Aghanim, you should have the webhook server configured as follows:

Configuration

Below are function templates designed for an endpoint that processes player verification events generated by Aghanim:

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 == "player.verify":
player_data = verify_player(event_data)
if not player_data:
raise fastapi.HTTPException( status_code=401, detail="Player verification failed")
return player_data

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 verify_player(event_data: dict[str, typing.Any]) -> dict[str, typing.Any]:
# Placeholder logic for fetching of player data.
# In a real application, this function would interact with your database or user management system.
return {
"player_id": "r2d2-c3po",
"name": "Molly",
"attributes": {"level": 2},
"country": "US"
}

Once your function is ready:

  1. Make your endpoint available.
  2. Register your endpoint within Aghanim account → GameWebhooksAdd webhook by choosing the player verification event type.

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

Trigger values

ValueDescription
hub.loginWhen the player opens the game hub.
hub.interactBackground re-verification, fires every 6 hours after the player's previous hub visit.
hub.purchaseWhen the player clicks the buy button in the store to confirm that the item is still available based on the player's attributes.
hub.store.openWhen the store is opened. Fires only when Store Rules include a verify_player action.
order.capturedJust before payment processing begins. Fires only when the Store item has segmentation rules.
s2s.user.authorizeOn the first S2S authorize call for a newly created user. Subsequent calls for the same user do not emit a webhook.
s2s.player.issue_loyalty_pointsOn the first S2S loyalty points issuance for a newly created user. Subsequent calls for the same user do not emit a webhook.
liveops.execute_actionWhen a LiveOps action is executed.
testWhen using the "Send test event" in the Dashboard.

See the full events and triggers matrix for how player.verify relates to other event types.

Request schema

Below is an example of an player.verify 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": "player.verify",
"event_data": {
"player_id": "2D2R-OP3C"
},
"event_time": 1725548450,
"event_id": "whevt_eCacGbJVbvToOgzjXUgOCitkQE",
"idempotency_key": null,
"request_id": "d1593e9c-c291-4004-8846-6679c2e5810b",
"sandbox": false,
"trigger": "hub.login",
"transaction_id": "whtx_eCacGbJVbvT",
"context": 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, player.verify in this case.
event_timenumberEvent date in Unix epoch time.
event_dataEventDataContains the event-specific data, with possible keys for inherited objects.
idempotency_keystring|nullEnsures webhook actions are executed only once, even if retried. Can be null depending on event type.
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.
contextobject|nullContextual information about the event.

The EventData schema

KeyTypeDescription
player_idstringThe unique Player ID chosen for player authentication.

Response schema

Upon receiving a player.verify webhook, your server must respond with the appropriate HTTP status code and JSON payload.

Success response

Return a 2xx status code with a JSON payload containing the player data when the player is verified successfully:

KeyTypeDescriptionRequired?
player_idstringUnique Player ID chosen for player authentication.Yes
namestringPlayer's nickname.Yes
attributesAttributesBasic player attributes expected by Aghanim.Yes
avatar_urlstringPlayer's avatar URL.No
emailstringPlayer's email address.No
bannedbooleanIndicates whether the player is banned in the game.No
segmentsstring[]Segments to which the player belongs.No
countrystringTwo-letter country code according to ISO 3166‑1.No
custom_attributesCustomAttributesCustom player attributes.No
balancesBalance[]Player's virtual currency balances.No

The Balance object

The Balance object contains the following fields:

KeyTypeDescriptionRequired?
skustringItem SKU matching on both the game and Aghanim sides linked to the virtual currency.Yes
quantitynumberPlayer's balance in the currency.Yes

The Attributes object

The Attributes object contains the following fields:

KeyTypeDescriptionRequired?
levelnumberPlayer's level in the game.Yes
platformstringThe platform on which the player is using the game hub. Possible values: ios, android.No
marketplacestringMarketplace from which the player originates. Possible values: app_store, google_play, other.No
soft_currency_amountnumberPlayer's soft currency balance.No
hard_currency_amountnumberPlayer's hard currency balance.No

The CustomAttributes object

The CustomAttributes object contains key-value pairs, for example:

{
"is_premium": true,
"age": 25,
"favorite_color": "blue",
"install_date": 1704070800
}

These attributes can be used later in LiveOps or Segmentation for constructing logic conditions to target specific player segments.

warning

Important: custom attributes must be declared in GamePlayer attributes.

Success response example

{
"player_id": "2D2R-OP3C",
"name": "Beebee-Ate",
"avatar_url": "https://static-platform.aghanim.com/images/bb8.jpg",
"attributes": {"level": 2},
"country": "US"
}

Error responses

When player verification fails, your server must return a 4xx status code with the following JSON structure:

{
"status": "error",
"code": "<error_code>",
"message": "<optional human-readable description>"
}

Aghanim uses the code field to determine how to handle the error. The message field is optional and used for logging purposes only.

HTTP StatusCodeDescriptionHub behavior
403player_bannedPlayer is banned in the game.Force logout. Player sees: "Your game account has been suspended."
404player_not_foundPlayer does not exist.Force logout. Player sees: "Your game account was not found. Please re-login through the game."
410player_deletedPlayer existed previously but has been deleted.Force logout. Player sees: "Your game account is no longer active."
422player_not_eligiblePlayer has not met the requirements to access the Hub (e.g. level, playtime, completed quests).Block access without logout. Player sees: "You haven't unlocked the Hub yet. Keep playing to gain access!"

Error response examples

{
"status": "error",
"code": "player_banned",
"message": "Player is banned"
}
{
"status": "error",
"code": "player_not_eligible",
"message": "Player has not reached the required level"
}
warning

Aghanim will only act on error responses that match the expected JSON format described above. If the response body is not valid JSON or does not contain the code field (e.g. an HTML error page returned by Cloudflare, a WAF, or a reverse proxy), Aghanim will treat it as an infrastructure-level error and will not force logout the player.

Server errors

Return a 5xx status code only for unexpected server-side failures (e.g. database unavailable, internal exception). Do not use 5xx codes to communicate player-level verification results. Aghanim does not retry player.verify requests that receive 5xx responses.

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