Webhook events
Every topic your app can subscribe to, the scope it requires, and the envelope every delivery shares.
On this page
Delivery envelope
Delivered for every subscribed topic. Verify X-Dukkan-Hmac-Sha256 (hex HMAC-SHA256 of {X-Dukkan-Timestamp}.{raw body} with the signing secret of the install named in the signed install_id), reject timestamps older than five minutes, deduplicate on the signed envelope id, and refuse a store_id that differs from the install you hold. sequence is strictly increasing per store with gaps — order by it, never count on contiguity. Topics require the matching granted scope (see x-dukkan-topic-scopes); app.uninstalled needs no scope and still delivers after revocation. Respond 2xx with a small body within the timeout; anything else is retried with exponential backoff up to 8 attempts, after which the delivery is dead-lettered and sustained failures disable the subscription. Sandbox rehearsals fired through POST /webhooks/test carry test: true.
Headers
| Name | Type | Description |
|---|---|---|
X-Dukkan-Delivery-IdheaderRequired | string | Delivery attempt id (unsigned; retries reuse it) |
X-Dukkan-Install-IdheaderRequired | string | Unsigned hint of the signed envelope install_id |
X-Dukkan-EventheaderRequired | WebhookTopic | Webhook topic. Subscribing needs the read scope that governs the payload; |
X-Dukkan-TimestampheaderRequired | string | Unix seconds |
X-Dukkan-Api-VersionheaderRequired | string | Dated v1 revision that produced this payload |
X-Dukkan-Hmac-Sha256headerRequired | string |
Request body
| Name | Type | Description |
|---|---|---|
idRequired | string | Event id. Deduplicate on this signed value, never on the delivery header. |
api_versionRequired | "v1" | |
topicRequired | WebhookTopic | Webhook topic. Subscribing needs the read scope that governs the payload; Values: order.createdorder.status_changedorder.paidproduct.createdproduct.updatedproduct.deletedinventory.movement_createdfulfillment.requestedfulfillment.createdfulfillment.updatedrefund.createdapp.uninstalled |
store_idRequired | string | |
install_idRequired | string | The install this delivery was fanned out to. Verify the signature with THIS install's secret and refuse a store mismatch. |
sequenceRequired | integer | Strictly increasing per store with gaps. Order by it; never count on contiguity. |
occurred_atRequired | string | |
test | boolean | Present and true only for sandbox test deliveries (POST /webhooks/test). Absent in production traffic. |
dataRequired | object |
{
"id": "9b2f6c1e-7d3a-4f0b-9a52-1c8e2d4b6a70",
"api_version": "v1",
"topic": "order.created",
"store_id": "3065a1f2-0c4d-4e8b-b7a9-5d2f8c1e9a44",
"install_id": "8b2c1d4e-5f60-4a7b-8c9d-0e1f2a3b4c5d",
"sequence": 1661,
"occurred_at": "2026-08-18T16:00:00.123Z",
"data": {
"order_id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
"order_number": "1042",
"status": "placed",
"total_minor": 275000,
"currency": "SYP"
}
}order.created#
Scope:orders:read
An order is created from any source.
{
"id": "9b2f6c1e-7d3a-4f0b-9a52-1c8e2d4b6a70",
"api_version": "v1",
"topic": "order.created",
"store_id": "3065a1f2-0c4d-4e8b-b7a9-5d2f8c1e9a44",
"install_id": "8b2c1d4e-5f60-4a7b-8c9d-0e1f2a3b4c5d",
"sequence": 1661,
"occurred_at": "2026-08-18T16:00:00.123Z",
"data": {
"order_id": "6f1d2c3b-4a59-4e8f-9b70-2d1c3e4f5a6b",
"order_number": "1042",
"status": "placed",
"total_minor": 275000,
"currency": "SYP"
}
}order.status_changed#
Scope:orders:read
Every order status transition.
No example for this topic yet.
order.paid#
Scope:orders:read
Actually-collected funds cross the order total in the payments ledger.
No example for this topic yet.
product.created#
Scope:products:read
A product is created.
No example for this topic yet.
product.updated#
Scope:products:read
A product or one of its variants changes.
No example for this topic yet.
product.deleted#
Scope:products:read
A product is deleted.
No example for this topic yet.
inventory.movement_created#
Scope:inventory:read
A new inventory movement is appended.
{
"movement_id": "0a1b2c3d-0001-4e8f-9b70-2d1c3e4f5a6b",
"variant_id": "c0ffee00-0001-4e8f-9b70-2d1c3e4f5a6b",
"location_id": "10c00000-0001-4e8f-9b70-2d1c3e4f5a6b",
"delta": -2,
"stock_after": 23,
"reason": "damage"
}fulfillment.requested#
Scope:orders:read
A fulfillment is created as pending: a pickup waiting to be booked.
No example for this topic yet.
fulfillment.created#
Scope:orders:read
Any fulfillment is created.
No example for this topic yet.
fulfillment.updated#
Scope:orders:read
A fulfillment status or tracking number changes.
No example for this topic yet.
refund.created#
Scope:orders:read
A refund is recorded.
No example for this topic yet.
app.uninstalled#
Scope:No scope required
The install is revoked; arrives even after tokens are revoked.
No example for this topic yet.