Delivery behaviour
Read from the vendor's own documentation, last checked 2026-08-06. Where the vendor states no number, this table carries none.
| Response budget | not published by the vendor |
|---|---|
| Retry | not published by the vendor |
| Gives up | not published by the vendor |
Signature
Verified against a working verifier proven by a test suite, not read from documentation. Last verified 2026-08-20.
| Algorithm | HMAC-SHA1 |
|---|---|
| Signed payload | raw body |
| Encoding | hex |
| Header | x-hub-signature = sha1=hex |
| Tolerance | none enforced |
Verify it
The raw request body, byte for byte, before any JSON parsing. Every scheme on this page breaks the moment a framework re-serializes the payload.
const crypto = require("node:crypto");
// x-hub-signature: "sha1=" + hex(HMAC-SHA1(client secret, raw body))
const expected =
"sha1=" +
crypto.createHmac("sha1", clientSecret).update(rawBody).digest("hex");
const valid = crypto.timingSafeEqual(
Buffer.from(req.headers["x-hub-signature"]),
Buffer.from(expected),
);What bites
The header is x-hub-signature — the SHA-1 original, not GitHub's x-hub-signature-256. Auto-detection code that matches on the prefix needs to check the whole header name or it verifies with the wrong algorithm and the wrong encoding.
Read more
AnyHook sits in front of endpoints that receive from Intercom: it answers inside the budget above, retries on its own schedule when your server is down, and keeps every event replayable. Change one URL, keep your code.