Notification Webhooks
A notification policy with thewebhook channel sends each matching event to your HTTPS
endpoint as a JSON POST. Each delivery is signed, so your endpoint can reject any request
that Qumo did not send.
The signing secret
When you create a webhook policy, Qumo generates its signing secret and returns it once, in the create response (signing_secret). In the console, it appears once, right after you
create the policy. No later response returns it. Store it with your receiver’s other
secrets.
To change the secret, delete the policy and create it again. The new policy has a new
secret.
Webhook policies created before signing was introduced have no secret. Qumo still delivers
to them, unsigned, so existing receivers keep working. To start verifying, delete the
policy and create it again.
What a delivery carries
The signature covers the timestamp as well as the body. A captured delivery therefore
cannot be replayed later with a new timestamp, and your receiver can reject an old one by
checking its age.
Verifying a delivery
- Read the raw request body before parsing it. Re-serialized JSON is not byte-for-byte the same, so its signature will not match.
- Compute HMAC-SHA256 over the
X-Notification-Timestampvalue, a., and the raw body, using the signing secret as the key. Hex-encode the result in lowercase. - Compare it with
X-Notification-Signature-256using a constant-time comparison. - Reject the delivery if the timestamp is more than a few minutes from your clock. Five minutes is a reasonable window.
Retries
A delivery that fails with a network error or a5xx response is retried with exponential
backoff for up to five minutes. Each attempt is signed again with a fresh timestamp. Use
the body’s notification_id to drop duplicates.
Slack and Discord policies are not signed. Those services authenticate the sender through
the secret in the webhook URL itself.