Subscription Webhooks
Aghanim's subscription webhooks notify your game about subscription lifecycle events, allowing you to manage player access to subscription-based content and services.
Webhook events
Use these webhook events to grant, extend, or revoke subscription access.
| Event | When it fires | What you should do |
|---|---|---|
subscription.activated | Subscription becomes active | Grant subscription benefits to the player |
subscription.updated | Subscription attributes change (status, plan, or billing dates) | Sync your internal state with the updated subscription data |
subscription.renewed | Recurring payment succeeds | Extend access by updating effective_until. Optionally, grant rewards on each successful renewal (if applicable) |
subscription.deactivated | Subscription is deactivated | Revoke subscription benefits immediately |
Webhook events may be delivered more than once, so handlers must be idempotent.
Subscription statuses
Statuses are used to track the current state of the subscription.
| Status | Description |
|---|---|
trial | The subscription is in a trial period. |
active | The subscription is paid and in good standing. |
canceled | The subscription will not renew. It remains active until effective_until, then transitions to expired. |
expired | The subscription is no longer active. |
New subscription statuses may be added in the future.
To keep your integration forward-compatible, do not rely on subscription statuses alone to grant or revoke benefits.
Always rely on event_type and effective_until as the source of truth for activating and deactivating subscription access.
Do not model status as a strict enum in your code — treat it as a string to avoid breaking when new values are introduced.
Common scenarios
The following examples show typical subscription flows and which events fire at each stage:
Trial → Paid
subscription.activatedstatus=trial→ Grant accesssubscription.updatedstatus=active→ Trial converts to paid (first successful payment), extendeffective_until
Recurring payment
subscription.renewedstatus=active→ Extend access (updateeffective_until)- (Optional) Grant rewards on each successful renewal (if applicable)
Cancellation
subscription.updatedstatus=canceled→ Access remains active untileffective_untilsubscription.deactivated→ Revoke access
Expiration
subscription.deactivatedstatus=expired→ Revoke access- (Optional) If you didn’t receive the webhook, revoke access when
now >= effective_until
Requirements
To use subscription webhooks 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 subscription event was processed successfully, and 4xx or 5xx for errors.
Configuration
- Develop a function for subscription webhook processing.
- Make your endpoint available.
- Register your endpoint within Aghanim account → Game → Webhooks → New Webhook by choosing the subscription event types you want to handle.
Alternatively, you can register your endpoint within Aghanim using the Create Webhook API method.
Request schema
아래는 예시입니다 subscription.activated 웹훅 요청:
- 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": "subscription.activated",
"event_data": {
"id": "sub_kMnoPqRsTuV",
"sku": "battle_pass",
"name": "Battle Pass",
"nested_items": [
{
"id": "itm_zzzzzzz",
"name": "Exclusive Skin",
"description": "Limited edition subscriber skin",
"sku": "exclusive_skin_001",
"quantity": 1,
"type": "item"
}
],
"order_id": "ord_eCacpFwavzi",
"user_id": "usr_eymySUreClx",
"player_id": "2D2R-OP3C",
"amount": 999,
"amount_decimal": 9.99,
"currency": "USD",
"payment_method": "cards",
"status": "active",
"due_at": 1706745600,
"created_at": 1704067200,
"plan": {
"key": "battle_pass_monthly",
"name": "Battle Pass Monthly",
"amount": 999,
"amount_decimal": 9.99,
"currency": "USD",
"offer": {
"key": "season_launch",
"name": "Season Launch Bonus",
"description": "Special discount for season launch",
"discount_percent": 20,
"grace_extension": 3,
"trial_extension": 7
},
"cycle_period": 30,
"grace_period": 3,
"trial_period": 7,
"nested_items": [
{
"id": "itm_xxxxxxx",
"name": "500 Bonus Gold",
"description": "Monthly bonus gold for subscribers",
"sku": "bonus_gold_500",
"quantity": 1,
"type": "item"
},
{
"id": "itm_yyyyyyy",
"name": "XP Boost",
"description": "25% XP boost active during subscription",
"sku": "xp_boost_25",
"quantity": 1,
"type": "item"
}
]
},
"effective_until": 1705276800,
"trial_due_at": 1705276800,
"paid_due_at": 1704067200,
"updated_at": 1704067200,
"metadata": {
"tier": "premium",
"referral_code": "SUMMER2024"
}
},
"event_time": 1725548450,
"event_id": "whevt_eCacGbJVbvToOgzjXUgOCitkQE",
"idempotency_key": "idmpt_aXRlb...JkX2VFS",
"request_id": "d1593e9c-c291-4004-8846-6679c2e5810b",
"sandbox": false,
"trigger": "subscription.activated",
"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": "subscription.activated",
"event_data": {
"id": "sub_kMnoPqRsTuV",
"sku": "battle_pass",
"name": "Battle Pass",
"nested_items": [
{
"id": "itm_zzzzzzz",
"name": "Exclusive Skin",
"description": "Limited edition subscriber skin",
"sku": "exclusive_skin_001",
"quantity": 1,
"type": "item"
}
],
"order_id": "ord_eCacpFwavzi",
"user_id": "usr_eymySUreClx",
"player_id": "2D2R-OP3C",
"amount": 999,
"amount_decimal": 9.99,
"currency": "USD",
"payment_method": "cards",
"status": "active",
"due_at": 1706745600,
"created_at": 1704067200,
"plan": {
"key": "battle_pass_monthly",
"name": "Battle Pass Monthly",
"amount": 999,
"amount_decimal": 9.99,
"currency": "USD",
"offer": {
"key": "season_launch",
"name": "Season Launch Bonus",
"description": "Special discount for season launch",
"discount_percent": 20,
"grace_extension": 3,
"trial_extension": 7
},
"cycle_period": 30,
"grace_period": 3,
"trial_period": 7,
"nested_items": [
{
"id": "itm_xxxxxxx",
"name": "500 Bonus Gold",
"description": "Monthly bonus gold for subscribers",
"sku": "bonus_gold_500",
"quantity": 1,
"type": "item"
},
{
"id": "itm_yyyyyyy",
"name": "XP Boost",
"description": "25% XP boost active during subscription",
"sku": "xp_boost_25",
"quantity": 1,
"type": "item"
}
]
},
"effective_until": 1705276800,
"trial_due_at": 1705276800,
"paid_due_at": 1704067200,
"updated_at": 1704067200,
"metadata": {
"tier": "premium",
"referral_code": "SUMMER2024"
}
},
"event_time": 1725548450,
"event_id": "whevt_eCacGbJVbvToOgzjXUgOCitkQE",
"idempotency_key": "idmpt_aXRlb...JkX2VFS",
"request_id": "d1593e9c-c291-4004-8846-6679c2e5810b",
"sandbox": false,
"trigger": "subscription.activated",
"transaction_id": "whtx_eCacGbJVbvT",
"context": null,
"game_id": "gm_exTAyxPsVwh"
}'
이벤트 스키마
| Key | 유형 | 설명 |
|---|---|---|
event_id | string | Aghanim에 의해 생성된 고유 이벤트 ID. |
game_id | string | Aghanim 시스템에서의 귀하의 게임 ID. |
event_type | string | 이벤트의 유형, subscription.activated 이럴 경우. |
event_time | number | 유닉스 에포크 시간으로 된 이벤트 날짜. |
event_data | EventData | 이벤트 특정 데이터가 포함되어 있으며, 상속된 객체에 대한 가능한 키가 포함됩니다. |
idempotency_key | string | 웹훅 작업이 재시도되어도 한 번만 실행되도록 보장합니다. |
request_id | string|null | 이벤트가 API 요청에 의해 트리거된 경우, 요청 ID 가 포함됩니다. |
sandbox | boolean | 이 이벤트가 샌드박스 게임 환경에서 전송되었는지를 표시합니다. |
trigger | string|null | The trigger that caused the event to be sent. |
transaction_id | string | Aghanim이 생성한 거래 ID입니다. 이 ID는 동일한 거래 내에서 발생한 여러 이벤트에서 동일할 수 있습니다. |
context | EventContext|null | 이벤트에 대한 컨텍스트 정보. |
EventContext 스키마
| Key | 유형 | 설명 |
|---|---|---|
order | OrderContext|null | 해당되는 경우 이벤트와 관련된 주문 정보입니다. |
player | PlayerContext|null | 플레이어 정보를 추가하려면 웹훅 설정에서 "플레이어 컨텍스트 추가"를 활성화하세요. |
The EventData schema
id | string | Unique identifier for this subscription instance. Use this ID to track and manage the subscription throughout its lifecycle. |
| Key | 유형 | 설명 |
|---|---|---|
sku | string | Subscription unique SKU. |
name | string | Subscription display name. |
nested_items | NestedItem[] | Items included in this subscription. |
order_id | string | Order ID where the subscription was originally activated. Use this to correlate with order webhooks. |
user_id | string | Aghanim 시스템에서 게임 허브 유저 ID. |
player_id | string | 고유한 플레이어 인증에 선택된 플레이어 ID. |
amount | number | Subscription amount in 소수 통화 단위. |
amount_decimal | number | Subscription amount in major currency units. |
currency | string | Subscription 통화. |
payment_method | string | Payment method used (cards, apple_pay, google_pay, paypal, etc.). |
status | string | Subscription status. See Subscription statuses above. |
due_at | number | Next payment due date in Unix epoch time (seconds). For trial subscriptions, this is when the first charge will occur. |
created_at | number | Subscription creation date in Unix epoch time (seconds). |
plan | Plan | Plan associated with the subscription. |
effective_until | number | The date until which the subscription is effective in Unix epoch time (seconds). This is the higher value between trial_due_at and paid_due_at, representing when the subscription benefits should remain accessible. |
trial_due_at | number|null | Trial end date in Unix epoch time (seconds). Null if subscription has no trial. |
paid_due_at | number|null | Date through which the subscription is paid (paid-through date) in Unix epoch time (seconds). After this date, the subscription must be renewed or it will become expired. Null during trial or before first payment. |
updated_at | number|null | Subscription last update date in Unix epoch time (seconds). Null if the subscription has not been updated. |
metadata | object|null | Custom key-value pairs attached to the subscription. Null if no metadata is set. |
The Plan schema
| Key | 유형 | 설명 |
|---|---|---|
key | string | Plan unique key within subscription. |
name | string | Plan display name. |
amount | number | Plan amount in 소수 통화 단위. |
amount_decimal | number | Plan amount in major currency units. |
currency | string | Plan 통화. |
offer | Offer|null | Offer applied to the plan. Null if no offer is applied. |
cycle_period | number|null | Recurring billing interval in days (e.g., 30 for monthly, 365 for yearly). |
grace_period | number|null | Number of days after a failed payment during which the subscription remains active while retry attempts are made. Null if no grace period is configured. |
trial_period | number|null | Trial period duration in days. Null if plan has no trial. |
nested_items | NestedItem[] | Items included in this plan. |
The Offer schema
| Key | 유형 | 설명 |
|---|---|---|
key | string | Offer unique key. |
name | string|null | Offer display name. |
description | string|null | Offer description. |
discount_percent | number|null | Discount percentage. |
grace_extension | number|null | Grace period extension in days. |
trial_extension | number|null | Trial period extension in days. |
NestedItem 스키마
| Key | 유형 | 설명 |
|---|---|---|
id | string | Aghanim에 의해 생성된 아이템 ID. |
name | string | 아이템 이름. |
description | string|null | 아이템 설명. |
sku | string | 게임과 Aghanim 측 모두에서 일치하는 아이템 SKU. |
quantity | number | 아이템 수량. |
type | string | 항목 유형. 가능한 값: item, bundle. |
nested_items | NestedItem[]|null | 번들에 포함된 항목 배열. |
도움이 필요하세요?
통합팀에 문의하십시오 integration@aghanim.com