Status: events flow between matgrk services and payment gateways today. Subscribing your own endpoint is not open yet — what follows is the envelope and signature scheme you will integrate against when it opens.
The envelope
Every event is one JSON object. id is unique per event and is the deduplication key; family groups related types (order, payment, subscription, gateway); data carries the type’s payload.
{
"id": "01J8…",
"version": 1,
"family": "order",
"type": "order.placed",
"occurred_at": "2026-09-26T02:00:00Z",
"tenant_id": "01HZ…",
"data": { … }
}Signatures
Every delivery is signed: an HMAC-SHA256 of the raw request body, hex-encoded, in X-Commerce-Signature for order events and X-Pay-Signature for payment events, as sha256=<hex>. An unsigned body is never sent. Verify by recomputing over the exact bytes received — before parsing the JSON — and comparing in constant time.
signature = request.headers["X-Commerce-Signature"] // "sha256=<hex>"
expected = "sha256=" + hmac_sha256_hex(secret, raw_request_body)
valid = constant_time_equal(signature, expected)Delivery
- At-least-once: the same event can arrive twice. Deduplicate on
id. - A failed delivery is retried with exponential backoff, capped at one hour between attempts.
- Answer with a 2xx quickly and do the work afterwards; a slow handler reads as a failure and is retried.
Subscriptions
Registering your own endpoint — choose the event families you want, receive them at your URL, verify with a per-subscription secret — is part of the planned public webhooks release. There is no subscription endpoint yet; when it ships it will be documented here, and the envelope and signature scheme above are what your handler will already be written against.
Order event types
order.placedorder.payment_state_changedorder.fulfilment_state_changedorder.return_state_changedorder.cancelled