gamification.chest.opened
Version 1 of the gamification.chest.opened webhook event.
A player opened one chest from their inventory. Published only once every cross-boundary drop has settled: a currency drop is settled when Reward Management applied its grant and rejected when it refused or the outcome timed out, so a consumer never learns of an open whose value is still outstanding. xp and battlePassXP drops settled inside the open transaction; a badge drop is settled by the badge intent Gamification persists. inventoryId is the open's identity — a redelivered open re-publishes this event under the same idempotency key rather than a second open.
| Event type | gamification.chest.opened |
| Schema version | 1 |
| Routing key | event.gamification.chest.opened.v1 |
| Produced by | Gamification |
| Schema | urn:defendr:contract:gamification:chest-opened:1 |
data fields
| Field | Type | Required | Description |
|---|---|---|---|
accountId | string | yes | |
playerId | string | yes | |
inventoryId | string | yes | |
chestType | "common", "rare", "epic", "legendary" | yes | |
openedAt | string (date-time) | yes | |
pity | object | yes | |
pity.floorApplied | "epic", "legendary", null | yes | |
pity.opensSinceEpic | integer | yes | |
pity.opensSinceLegendary | integer | yes | |
drops | array of object | yes | |
drops[].rewardType | "xp", "battlePassXP", "currency", "badge" | yes | |
drops[].rarity | "common", "rare", "epic", "legendary" | yes | |
drops[].amount | integer or null | yes | |
drops[].key | string or null | yes | |
drops[].settlement | "settled", "rejected" | yes |
Some fields are required only in particular states. The JSON Schema below is authoritative.
Example delivery
Signed with the example secret whsec_placeholder_example_webhooks_signing_secret, so you can check your verifier against it. See Verifying signatures.
POST /your/webhook/endpoint HTTP/1.1
content-type: application/json
webhook-id: whd_00000000-0000-4000-8000-000000000016
webhook-timestamp: 1800000000
webhook-signature: v1,spnkeMoYnsxIlJw6c1DeG+SQgnhJ0PZbG+vs8Nv7zNY=
tanitar-event-type: gamification.chest.opened
tanitar-schema-version: 1
tanitar-delivery-attempt: 1
{"messageId":"evt_00000000-0000-4000-8000-000000000016","kind":"event","type":"gamification.chest.opened","schemaVersion":1,"occurredAt":"2027-01-15T10:00:00.000Z","producer":"gamification-service","accountId":"acc_11111111-1111-4111-8111-111111111111","correlationId":"corr_00000000-0000-4000-8000-000000000016","data":{"accountId":"acct_demo","playerId":"player_demo","inventoryId":"66e0a1b2c3d4e5f6a7b8c9d0","chestType":"common","openedAt":"2026-09-11T00:00:00.000Z","pity":{"floorApplied":"epic","opensSinceEpic":0,"opensSinceLegendary":10},"drops":[{"rewardType":"battlePassXP","rarity":"epic","amount":156,"key":null,"settlement":"settled"}]}}The same body, formatted:
{
"messageId": "evt_00000000-0000-4000-8000-000000000016",
"kind": "event",
"type": "gamification.chest.opened",
"schemaVersion": 1,
"occurredAt": "2027-01-15T10:00:00.000Z",
"producer": "gamification-service",
"accountId": "acc_11111111-1111-4111-8111-111111111111",
"correlationId": "corr_00000000-0000-4000-8000-000000000016",
"data": {
"accountId": "acct_demo",
"playerId": "player_demo",
"inventoryId": "66e0a1b2c3d4e5f6a7b8c9d0",
"chestType": "common",
"openedAt": "2026-09-11T00:00:00.000Z",
"pity": {
"floorApplied": "epic",
"opensSinceEpic": 0,
"opensSinceLegendary": 10
},
"drops": [
{
"rewardType": "battlePassXP",
"rarity": "epic",
"amount": 156,
"key": null,
"settlement": "settled"
}
]
}
}JSON Schema
urn:defendr:contract:gamification:chest-opened:1
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "urn:defendr:contract:gamification:chest-opened:1",
"title": "Gamification chest opened event payload",
"description": "A player opened one chest from their inventory. Published only once every cross-boundary drop has settled: a currency drop is `settled` when Reward Management applied its grant and `rejected` when it refused or the outcome timed out, so a consumer never learns of an open whose value is still outstanding. `xp` and `battlePassXP` drops settled inside the open transaction; a `badge` drop is settled by the badge intent Gamification persists. `inventoryId` is the open's identity — a redelivered open re-publishes this event under the same idempotency key rather than a second open.",
"type": "object",
"additionalProperties": false,
"required": [
"accountId",
"playerId",
"inventoryId",
"chestType",
"openedAt",
"pity",
"drops"
],
"properties": {
"accountId": {
"type": "string",
"minLength": 1
},
"playerId": {
"type": "string",
"minLength": 1
},
"inventoryId": {
"type": "string",
"minLength": 1
},
"chestType": {
"enum": [
"common",
"rare",
"epic",
"legendary"
]
},
"openedAt": {
"type": "string",
"format": "date-time"
},
"pity": {
"type": "object",
"additionalProperties": false,
"required": [
"floorApplied",
"opensSinceEpic",
"opensSinceLegendary"
],
"properties": {
"floorApplied": {
"enum": [
"epic",
"legendary",
null
]
},
"opensSinceEpic": {
"type": "integer",
"minimum": 0
},
"opensSinceLegendary": {
"type": "integer",
"minimum": 0
}
}
},
"drops": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"rewardType",
"rarity",
"amount",
"key",
"settlement"
],
"properties": {
"rewardType": {
"enum": [
"xp",
"battlePassXP",
"currency",
"badge"
]
},
"rarity": {
"enum": [
"common",
"rare",
"epic",
"legendary"
]
},
"amount": {
"type": [
"integer",
"null"
],
"minimum": 1
},
"key": {
"type": [
"string",
"null"
],
"minLength": 1
},
"settlement": {
"enum": [
"settled",
"rejected"
]
}
}
}
}
}
}