Agent skill
Heroku Webhooks Skill
Receive and verify Heroku app webhooks. Use when setting up Heroku webhook handlers, debugging Heroku-Webhook-Hmac-SHA256 signature verification, or handling app events like api:release, api:build, api:dyno, api:formation, and api:addon-attachment.
Install this skill
npx skills add hookdeck/webhook-skills --skill heroku-webhooks
When to Use This Skill
- How do I receive Heroku app webhooks?
- How do I verify the
Heroku-Webhook-Hmac-SHA256signature? - How do I handle
api:releaseorapi:buildevents (deploy notifications)? - Why is my Heroku webhook signature verification failing?
- How do I use
heroku webhooks:addwith--secretand--authorization?
Verification (core)
Heroku sends Heroku-Webhook-Hmac-SHA256: the base64 HMAC-SHA256 of the raw request body, keyed with the webhook secret. The secret is used as a raw string (not base64-decoded). There is no timestamp or webhook ID header, and Heroku has no webhook verification SDK, so verification is manual.
Node:
const crypto = require('crypto');
function verify(rawBody, hmacHeader, secret) {
if (!hmacHeader) return false;
const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('base64');
try {
return crypto.timingSafeEqual(Buffer.from(hmacHeader), Buffer.from(expected));
} catch {
return false; // different lengths
}
}
Python:
import base64, hashlib, hmac
def verify(raw_body: bytes, hmac_header: str, secret: str) -> bool:
if not hmac_header:
return False
expected = base64.b64encode(
hmac.new(secret.encode(), raw_body, hashlib.sha256).digest()
).decode()
return hmac.compare_digest(hmac_header, expected)
Optional extra: if you subscribed with
--authorization, Heroku also sends that exact value in theAuthorizationheader. Compare it yourself; it is not a signature.Respond with any 2xx (Heroku recommends
204 No Content); the body is ignored.
For complete handlers with route wiring, event dispatch, and tests, see:
Common Event Types
A subscription lists entities with -i; each delivery carries a resource (the entity) and an action (create, update, or destroy) plus data.
Entity (-i) | Actions | Description |
|---|---|---|
api:release | create, update | New release; with release phase you get create, update, update |
api:build | create, update | Build started / finished (check data.status) |
api:app | create, update, destroy | App created, changed, or deleted |
api:dyno | create | Dyno started |
api:formation | update, destroy | Process type scaled or removed |
api:addon-attachment | create, destroy | Add-on attached or detached |
api:addon, api:collaborator, api:domain, api:sni-endpoint | see overview | Other entities |
For the full list, see Heroku App Webhooks.
Environment Variables
HEROKU_WEBHOOK_SECRET=your_webhook_secret # --secret value, or the one the CLI printed once
HEROKU_WEBHOOK_AUTHORIZATION=Bearer your_token # Optional: the --authorization value
Local Development
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 heroku --path /webhooks/heroku
Reference Materials
- references/overview.md - Heroku webhook concepts, entities, payload shape
- references/setup.md -
heroku webhooks:addand secret handling - references/verification.md - Signature verification details and gotchas