Appearance
For the operator's engineer building the webhook.receive module.
webhook.receive
The webhook.receive module is where OneHazel delivers events to you: KYC verdicts, responsible-gaming actions, payment outcomes and the like. It uses OneHazel's existing webhook delivery format unchanged, so a receiver you already run for OneHazel webhooks keeps working.
Who calls whom
OneHazel calls you, at POST /webhook under the base URL you register for webhook.receive. The body carries type, data, operatorId, timestamp and deliveryId.
Headers and signature
This module uses a different signature from wallet and player, on purpose:
| Header | Value |
|---|---|
X-OneHazel-Signature | sha256=<hex>, HMAC-SHA256 of the raw body keyed by your whsec_ signing secret. No timestamp. |
X-OneHazel-Event | the same value as body type |
X-OneHazel-Delivery | the same value as body deliveryId |
There is no bearer. Live deliveries carry no X-OneHazel-Env; conformance deliveries add X-OneHazel-Env: test, so do not reject a delivery for having or lacking it.
Verify the signature over the raw bytes before parsing and compare in constant time. Answer 401 on a mismatch.
Replays and timing
With no timestamp, a replayed delivery verifies. Deduplicate on deliveryId: that is the replay defence. Deliveries are at-least-once, so the same deliveryId can arrive twice; answer 2xx both times and process it once.
Answer 2xx within 5 seconds and do slow work after acknowledging. Anything else, including a timeout, is retried on the subscription's retry policy.
Conformance
| Scenario | Severity | Passing looks like |
|---|---|---|
deliver.ok | blocker | 2xx for a correctly signed delivery |
deliver.replay_ignored | major | 2xx both times for the same deliveryId |
deliver.tampered_rejected | blocker | non-2xx for a body altered after signing |
deliver.timeout_5s | major | the 2xx arrives within 5 s |
Samples
| Stack | Sample |
|---|---|
| TypeScript + Express | webhook.receive |
| TypeScript + Fastify | webhook.receive |
| Python + FastAPI | webhook.receive |
| PHP (no framework) | webhook.receive |
| PHP + Laravel | webhook.receive |
The TypeScript helper @onehazel/connect exports verifyWebhookSignature for this format; see the contract.