shop.order.settled
Version 1 of the shop.order.settled webhook event.
One Shop order reached its placement outcome in Reward Management: settled when every line was charged and delivered in one tenant transaction, awaiting-fulfillment when a single manual line was charged and now waits on an attributed operator action, and rejected when admission refused the order durably (insufficient funds, sold out, limit reached, unpublished, retired, price changed). A rejection is a settled outcome with a typed reason, never a dropped request. Exactly one of these is published per order, in the same transaction as its ledger effect. No line discloses a delivered code.
| Event type | shop.order.settled |
| Schema version | 1 |
| Routing key | event.shop.order.settled.v1 |
| Produced by | Reward Management |
| Schema | urn:defendr:contract:shop:order-settled:1 |
data fields
| Field | Type | Required | Description |
|---|---|---|---|
orderId | string | yes | |
playerId | string | yes | |
purchaseKind | "cart", "direct" | yes | |
outcome | "settled", "awaiting-fulfillment", "rejected" | yes | |
lines | array of object | yes | |
lines[].listingKey | string | yes | |
lines[].listingRevision | integer | yes | |
lines[].quantity | integer | yes | |
lines[].fulfillmentKind | "award", "code", "manual" | yes | |
lines[].awardKey | string or null | yes | |
lines[].basePrice | array of object | yes | The listing's undiscounted price, pinned on the order. |
lines[].basePrice[].currencyKey | string | yes | |
lines[].basePrice[].amount | string | yes | A whole amount of the tenant's published currency, as a decimal string. |
lines[].effectivePrice | array of object | yes | The price actually charged for one unit, pinned on the order. |
lines[].effectivePrice[].currencyKey | string | yes | |
lines[].effectivePrice[].amount | string | yes | A whole amount of the tenant's published currency, as a decimal string. |
lines[].discount | object or null | yes | |
lines[].discount.kind | "percentage", "absolute" | yes | |
lines[].discount.percentage | string or null | yes | The percentage taken off, as a decimal string between 0 and 100; null for an absolute discount. |
lines[].discount.absolute | array or null | yes | The amount taken off per currency leg; null for a percentage discount. |
lines[].discount.absolute[].currencyKey | string | yes | |
lines[].discount.absolute[].amount | string | yes | A whole amount of the tenant's published currency, as a decimal string. |
lines[].discount.appliedAt | string (date-time) | yes | |
total | array of object | yes | The sum of every line's effective price, per currency leg. |
total[].currencyKey | string | yes | |
total[].amount | string | yes | A whole amount of the tenant's published currency, as a decimal string. |
rejection | object or null | yes | |
rejection.reasonCode | string | yes | |
rejection.reason | string | yes | |
placedAt | 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-000000000031
webhook-timestamp: 1800000000
webhook-signature: v1,w3/O/QhfHdi7xT+NyOdDJVeL+DKN+2CNvyWBNrt3uxA=
tanitar-event-type: shop.order.settled
tanitar-schema-version: 1
tanitar-delivery-attempt: 1
{"messageId":"evt_00000000-0000-4000-8000-000000000031","kind":"event","type":"shop.order.settled","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-000000000031","data":{"orderId":"ord_0123456789abcdef0123456789abcdef","playerId":"player_demo","purchaseKind":"cart","outcome":"settled","lines":[{"listingKey":"founder-badge","listingRevision":3,"quantity":1,"fulfillmentKind":"award","awardKey":"founder","basePrice":[{"currencyKey":"red","amount":"500"}],"effectivePrice":[{"currencyKey":"red","amount":"400"}],"discount":{"kind":"percentage","percentage":"20","absolute":null,"appliedAt":"2026-09-27T00:00:00.000Z"}}],"total":[{"currencyKey":"red","amount":"400"}],"rejection":null,"placedAt":"2026-09-27T00:00:00.000Z"}}The same body, formatted:
{
"messageId": "evt_00000000-0000-4000-8000-000000000031",
"kind": "event",
"type": "shop.order.settled",
"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-000000000031",
"data": {
"orderId": "ord_0123456789abcdef0123456789abcdef",
"playerId": "player_demo",
"purchaseKind": "cart",
"outcome": "settled",
"lines": [
{
"listingKey": "founder-badge",
"listingRevision": 3,
"quantity": 1,
"fulfillmentKind": "award",
"awardKey": "founder",
"basePrice": [
{
"currencyKey": "red",
"amount": "500"
}
],
"effectivePrice": [
{
"currencyKey": "red",
"amount": "400"
}
],
"discount": {
"kind": "percentage",
"percentage": "20",
"absolute": null,
"appliedAt": "2026-09-27T00:00:00.000Z"
}
}
],
"total": [
{
"currencyKey": "red",
"amount": "400"
}
],
"rejection": null,
"placedAt": "2026-09-27T00:00:00.000Z"
}
}JSON Schema
urn:defendr:contract:shop:order-settled:1
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "urn:defendr:contract:shop:order-settled:1",
"title": "Shop order settled",
"description": "One Shop order reached its placement outcome in Reward Management: `settled` when every line was charged and delivered in one tenant transaction, `awaiting-fulfillment` when a single manual line was charged and now waits on an attributed operator action, and `rejected` when admission refused the order durably (insufficient funds, sold out, limit reached, unpublished, retired, price changed). A rejection is a settled outcome with a typed reason, never a dropped request. Exactly one of these is published per order, in the same transaction as its ledger effect. No line discloses a delivered code.",
"type": "object",
"additionalProperties": false,
"required": [
"orderId",
"playerId",
"purchaseKind",
"outcome",
"lines",
"total",
"rejection",
"placedAt"
],
"properties": {
"orderId": {
"type": "string",
"pattern": "^ord_[a-f0-9]{32}$"
},
"playerId": {
"type": "string",
"minLength": 1
},
"purchaseKind": {
"enum": [
"cart",
"direct"
]
},
"outcome": {
"enum": [
"settled",
"awaiting-fulfillment",
"rejected"
]
},
"lines": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"listingKey",
"listingRevision",
"quantity",
"fulfillmentKind",
"awardKey",
"basePrice",
"effectivePrice",
"discount"
],
"properties": {
"listingKey": {
"type": "string",
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
},
"listingRevision": {
"type": "integer",
"minimum": 1
},
"quantity": {
"type": "integer",
"minimum": 1
},
"fulfillmentKind": {
"enum": [
"award",
"code",
"manual"
]
},
"awardKey": {
"type": [
"string",
"null"
],
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
},
"basePrice": {
"type": "array",
"minItems": 1,
"description": "The listing's undiscounted price, pinned on the order.",
"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."
}
}
}
},
"effectivePrice": {
"type": "array",
"minItems": 1,
"description": "The price actually charged for one unit, pinned on the order.",
"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."
}
}
}
},
"discount": {
"type": [
"object",
"null"
],
"additionalProperties": false,
"required": [
"kind",
"percentage",
"absolute",
"appliedAt"
],
"properties": {
"kind": {
"enum": [
"percentage",
"absolute"
]
},
"percentage": {
"type": [
"string",
"null"
],
"pattern": "^(?:100(?:\\.0{1,4})?|[0-9]{1,2}(?:\\.[0-9]{1,4})?)$",
"description": "The percentage taken off, as a decimal string between 0 and 100; null for an absolute discount."
},
"absolute": {
"type": [
"array",
"null"
],
"description": "The amount taken off per currency leg; null for a percentage discount.",
"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."
}
}
}
},
"appliedAt": {
"type": "string",
"format": "date-time"
}
},
"allOf": [
{
"if": {
"type": "object",
"required": [
"kind"
],
"properties": {
"kind": {
"const": "percentage"
}
}
},
"then": {
"type": "object",
"properties": {
"percentage": {
"type": "string"
},
"absolute": {
"type": "null"
}
}
}
},
{
"if": {
"type": "object",
"required": [
"kind"
],
"properties": {
"kind": {
"const": "absolute"
}
}
},
"then": {
"type": "object",
"properties": {
"percentage": {
"type": "null"
},
"absolute": {
"type": "array"
}
}
}
}
]
}
}
}
},
"total": {
"type": "array",
"minItems": 1,
"description": "The sum of every line's effective price, 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."
}
}
}
},
"rejection": {
"type": [
"object",
"null"
],
"additionalProperties": false,
"required": [
"reasonCode",
"reason"
],
"properties": {
"reasonCode": {
"type": "string",
"pattern": "^[A-Z0-9_]+$"
},
"reason": {
"type": "string",
"minLength": 1
}
}
},
"placedAt": {
"type": "string",
"format": "date-time"
}
},
"allOf": [
{
"if": {
"type": "object",
"required": [
"outcome"
],
"properties": {
"outcome": {
"enum": [
"settled",
"awaiting-fulfillment"
]
}
}
},
"then": {
"type": "object",
"properties": {
"rejection": {
"type": "null"
}
}
}
},
{
"if": {
"type": "object",
"required": [
"outcome"
],
"properties": {
"outcome": {
"const": "rejected"
}
}
},
"then": {
"type": "object",
"properties": {
"rejection": {
"type": "object"
}
}
}
},
{
"if": {
"type": "object",
"required": [
"outcome"
],
"properties": {
"outcome": {
"const": "awaiting-fulfillment"
}
}
},
"then": {
"type": "object",
"properties": {
"purchaseKind": {
"const": "direct"
},
"lines": {
"type": "array",
"maxItems": 1,
"items": {
"type": "object",
"properties": {
"fulfillmentKind": {
"const": "manual"
}
}
}
}
}
}
},
{
"if": {
"type": "object",
"required": [
"purchaseKind"
],
"properties": {
"purchaseKind": {
"const": "cart"
}
}
},
"then": {
"type": "object",
"properties": {
"lines": {
"type": "array",
"items": {
"type": "object",
"properties": {
"fulfillmentKind": {
"enum": [
"award",
"code"
]
}
}
}
}
}
}
},
{
"if": {
"type": "object",
"required": [
"outcome"
],
"properties": {
"outcome": {
"const": "settled"
}
}
},
"then": {
"type": "object",
"properties": {
"lines": {
"type": "array",
"items": {
"type": "object",
"properties": {
"fulfillmentKind": {
"enum": [
"award",
"code"
]
}
}
}
}
}
}
}
]
}