This guide takes you from zero to a verified, production-shaped webhook delivery in five minutes. Read Overview for the underlying delivery semantics, payload anatomy, and versioning policy.
Before you start
You’ll need:
- A Quo API key with permission to manage webhooks.
- An HTTPS endpoint you control. For local development, use a tunnel such as
ngrok or cloudflared.
- A runtime that gives you the raw, unparsed request body. This is required for signature verification — see Validate webhook signatures for framework-specific notes.
You can send a real, signed test event before any code is written using POST /webhooks/:id/events/test. See step 4 below.
1. Create the webhook
Pin the subscription to the current API version with Quo-Api-Version. The version is recorded once when the webhook is created and used for every subsequent delivery.
Save the key field from the response — that’s your whsec_… signing secret. Treat it like a credential: store it as an environment variable, never in source.
2. Receive the delivery
Each delivery sets three headers and a JSON body. Verify the signature against the raw bytes of the body, then parse.
3. Verify and handle the event
The Svix SDK accepts Quo’s headers and whsec_… key format unchanged. Reject any delivery whose timestamp is more than five minutes off from your server clock to defeat replay.
Return 200 to acknowledge. Any non-2xx response triggers a retry.
4. Send a test event
Trigger a real, signed delivery to your endpoint without waiting for a real call or message. The response also includes the sample payload inline so you can confirm what your endpoint received.
If verification fails, the most common cause is a framework that parsed the JSON before your handler saw the bytes. See Validate webhook signatures.
5. Inspect deliveries
Every delivery is recorded. Use these endpoints to debug a missing or failing event:
GET /webhooks/:id/events — recent deliveries with status.
GET /webhooks/:id/events/:eventId — request body, all attempts, response codes.
POST /webhooks/:id/events/:eventId/retry — manually retry a failed delivery.
Next steps