Agent skill
Northflank Webhooks Skill
Receive and authenticate Northflank webhook notifications. Use when building an endpoint for a Northflank webhook notification integration, checking the X-Northflank-Notification-Integration-Token secret, debugging 401s, or handling events like build:success, build:failure, job-run:failure, addon-backup:failure and billing:invoice-payment-failed.
Install this skill
npx skills add hookdeck/webhook-skills --skill northflank-webhooks
Northflank is a cloud deployment platform. A webhook notification integration POSTs a JSON event to your URL when something happens (a build finishes, a job run fails, a backup completes, an invoice is paid). Northflank does not sign the payload. If you set a secret on the integration, it is sent unchanged in the X-Northflank-Notification-Integration-Token header, and your endpoint checks it against NORTHFLANK_.
When to Use This Skill
- How do I receive Northflank webhooks?
- How do I verify the X-Northflank-Notification-Integration-Token header?
- Does Northflank sign webhook payloads? (No: it sends a shared secret token)
- How do I handle build:success, build:failure or job-run:failure events?
- Why does my Northflank webhook endpoint return 401?
Verification (core)
The secret is optional in Northflank, so set one on the integration, or anyone who finds your URL can post to it. Compare the header with a constant-time check:
const crypto = require('crypto');
// Hash both sides: equal-length buffers, so timingSafeEqual never throws.
function safeEqual(a, b) {
const ha = crypto.createHash('sha256').update(String(a)).digest();
const hb = crypto.createHash('sha256').update(String(b)).digest();
return crypto.timingSafeEqual(ha, hb);
}
function verifyNorthflankRequest(headers, secret = process.env.NORTHFLANK_WEBHOOK_SECRET) {
if (!secret) return false; // never accept when unconfigured
const token = headers['x-northflank-notification-integration-token'];
return Boolean(token) && safeEqual(token, secret);
}
Return 401 when this fails, 400 for a body that isn't a JSON object, and 2xx once handled. There is no signature, so the body isn't part of verification, but read it raw (express.raw({ type: '*/*' })) and authenticate before parsing. Python equivalent (hmac.compare_digest) is in references/verification.md.
For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.
Event Types
The body is {"event": "<type>", "data": {...}}; the type is also sent in the X-Northflank-Notification-Integration-Event-Type header. The examples handle:
| Event | Sent When |
|---|---|
build:start | A build starts (payload shown in the docs) |
build:success | A build succeeds |
build:failure | A build fails |
service:deployment:status-update | A deployment's status changes |
job-run:failure | A job run fails |
addon-backup:success | An addon backup completes |
addon-backup:failure | An addon backup fails |
billing:invoice-payment-failed | An invoice payment fails |
More types (build:abort, job-run:start|success|abort|terminate, addon-backup:start|abort, billing:invoice-paid, infrastructure alerts and others) are listed in references/overview.md.
Environment Variables
NORTHFLANK_WEBHOOK_SECRET=replace-with-a-long-random-secret # same value as the integration's Secret
Local Development
Northflank can't reach localhost. Tunnel with the Hookdeck CLI (no account required):
npx hookdeck-cli listen 3000 northflank --path /webhooks/northflank
Use the printed URL as the integration's webhook URL.
Resources
- references/overview.md - How notifications work, request format, event types
- references/setup.md - Create the webhook integration and set the secret
- references/verification.md - Token check in Node and Python, gotchas, debugging 401s
- examples/ - Runnable Express, Next.js and FastAPI handlers with tests