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_WEBHOOK_SECRET.

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:

EventSent When
build:startA build starts (payload shown in the docs)
build:successA build succeeds
build:failureA build fails
service:deployment:status-updateA deployment's status changes
job-run:failureA job run fails
addon-backup:successAn addon backup completes
addon-backup:failureAn addon backup fails
billing:invoice-payment-failedAn 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


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Nov 3, 2026

View on GitHub →