shop.order.reversed
Version 1 of the shop.order.reversed webhook event.
A settled Shop order was undone: by an attributed operator reversal, or by the Player's own self-cancel of a manual order an operator had not yet claimed. The currency is always credited back through one compensating, idempotent ledger operation; goods recovery is kind-dependent and stated per line - an award is revoked, a manual item was never delivered, and a delivered code cannot be un-delivered, so the loss is recorded and accepted explicitly. The consumed code itself is never disclosed here.
| Event type | shop.order.reversed |
| Schema version | 1 |
| Routing key | event.shop.order.reversed.v1 |
| Produced by | Reward Management |
| Schema | urn:defendr:contract:shop:order-reversed:1 |
data fields
| Field | Type | Required | Description |
|---|---|---|---|
orderId | string | yes | |
playerId | string | yes | |
initiator | "operator", "player" | yes | |
actorId | string or null | yes | The operator who reversed the order; null for a Player self-cancel, whose actor is the Player already named by playerId. |
reasonCode | string | yes | |
reason | string | yes | |
refund | array of object | yes | The compensating credit returned to the Player's wallet, per currency leg. |
refund[].currencyKey | string | yes | |
refund[].amount | string | yes | A whole amount of the tenant's published currency, as a decimal string. |
lines | array of object | yes | |
lines[].listingKey | string | yes | |
lines[].fulfillmentKind | "award", "code", "manual" | yes | |
lines[].recovery | "award-revoked", "never-delivered", "code-loss-accepted" | yes | |
reversedAt | string (date-time) | 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-000000000030
webhook-timestamp: 1800000000
webhook-signature: v1,paYP9zW1+MfTa5Y8rba1BHKVp0md0pNBw6x7qwXSLO4=
tanitar-event-type: shop.order.reversed
tanitar-schema-version: 1
tanitar-delivery-attempt: 1
{"messageId":"evt_00000000-0000-4000-8000-000000000030","kind":"event","type":"shop.order.reversed","schemaVersion":1,"occurredAt":"2027-01-15T10:00:00.000Z","producer":"reward-management-service","accountId":"acc_11111111-1111-4111-8111-111111111111","correlationId":"corr_00000000-0000-4000-8000-000000000030","data":{"orderId":"ord_0123456789abcdef0123456789abcdef","playerId":"player_demo","initiator":"operator","actorId":"operator_demo","reasonCode":"OPERATOR_CORRECTION","reason":"Listing was priced incorrectly.","refund":[{"currencyKey":"red","amount":"400"}],"lines":[{"listingKey":"founder-badge","fulfillmentKind":"award","recovery":"award-revoked"}],"reversedAt":"2026-09-27T00:00:00.000Z"}}The same body, formatted:
{
"messageId": "evt_00000000-0000-4000-8000-000000000030",
"kind": "event",
"type": "shop.order.reversed",
"schemaVersion": 1,
"occurredAt": "2027-01-15T10:00:00.000Z",
"producer": "reward-management-service",
"accountId": "acc_11111111-1111-4111-8111-111111111111",
"correlationId": "corr_00000000-0000-4000-8000-000000000030",
"data": {
"orderId": "ord_0123456789abcdef0123456789abcdef",
"playerId": "player_demo",
"initiator": "operator",
"actorId": "operator_demo",
"reasonCode": "OPERATOR_CORRECTION",
"reason": "Listing was priced incorrectly.",
"refund": [
{
"currencyKey": "red",
"amount": "400"
}
],
"lines": [
{
"listingKey": "founder-badge",
"fulfillmentKind": "award",
"recovery": "award-revoked"
}
],
"reversedAt": "2026-09-27T00:00:00.000Z"
}
}JSON Schema
urn:defendr:contract:shop:order-reversed:1
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "urn:defendr:contract:shop:order-reversed:1",
"title": "Shop order reversed",
"description": "A settled Shop order was undone: by an attributed operator reversal, or by the Player's own self-cancel of a manual order an operator had not yet claimed. The currency is always credited back through one compensating, idempotent ledger operation; goods recovery is kind-dependent and stated per line - an `award` is revoked, a `manual` item was never delivered, and a delivered `code` cannot be un-delivered, so the loss is recorded and accepted explicitly. The consumed code itself is never disclosed here.",
"type": "object",
"additionalProperties": false,
"required": [
"orderId",
"playerId",
"initiator",
"actorId",
"reasonCode",
"reason",
"refund",
"lines",
"reversedAt"
],
"properties": {
"orderId": {
"type": "string",
"pattern": "^ord_[a-f0-9]{32}$"
},
"playerId": {
"type": "string",
"minLength": 1
},
"initiator": {
"enum": [
"operator",
"player"
]
},
"actorId": {
"type": [
"string",
"null"
],
"description": "The operator who reversed the order; null for a Player self-cancel, whose actor is the Player already named by `playerId`."
},
"reasonCode": {
"type": "string",
"pattern": "^[A-Z0-9_]+$"
},
"reason": {
"type": "string",
"minLength": 1
},
"refund": {
"type": "array",
"minItems": 1,
"description": "The compensating credit returned to the Player's wallet, per currency leg.",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"currencyKey",
"amount"
],
"properties": {
"currencyKey": {
"type": "string",
"pattern": "^[a-z][a-z0-9-]*$"
},
"amount": {
"type": "string",
"pattern": "^[0-9]+$",
"description": "A whole amount of the tenant's published currency, as a decimal string."
}
}
}
},
"lines": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"listingKey",
"fulfillmentKind",
"recovery"
],
"properties": {
"listingKey": {
"type": "string",
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
},
"fulfillmentKind": {
"enum": [
"award",
"code",
"manual"
]
},
"recovery": {
"enum": [
"award-revoked",
"never-delivered",
"code-loss-accepted"
]
}
},
"allOf": [
{
"if": {
"type": "object",
"required": [
"fulfillmentKind"
],
"properties": {
"fulfillmentKind": {
"const": "award"
}
}
},
"then": {
"type": "object",
"properties": {
"recovery": {
"const": "award-revoked"
}
}
}
},
{
"if": {
"type": "object",
"required": [
"fulfillmentKind"
],
"properties": {
"fulfillmentKind": {
"const": "manual"
}
}
},
"then": {
"type": "object",
"properties": {
"recovery": {
"const": "never-delivered"
}
}
}
},
{
"if": {
"type": "object",
"required": [
"fulfillmentKind"
],
"properties": {
"fulfillmentKind": {
"const": "code"
}
}
},
"then": {
"type": "object",
"properties": {
"recovery": {
"const": "code-loss-accepted"
}
}
}
}
]
}
},
"reversedAt": {
"type": "string",
"format": "date-time"
}
},
"allOf": [
{
"if": {
"type": "object",
"required": [
"initiator"
],
"properties": {
"initiator": {
"const": "player"
}
}
},
"then": {
"type": "object",
"properties": {
"actorId": {
"type": "null"
}
}
}
},
{
"if": {
"type": "object",
"required": [
"initiator"
],
"properties": {
"initiator": {
"const": "operator"
}
}
},
"then": {
"type": "object",
"properties": {
"actorId": {
"type": "string"
}
}
}
}
]
}