Agent skill
Bump.sh Webhooks Skill
Receive and verify Bump.sh webhooks. Use when setting up Bump.sh webhook handlers, debugging X-Bump-Signature-256 signature verification, or reacting to API documentation structure changes (the {api, diff} payload sent when a deployment changes your API's structure).
Install this skill
npx skills add hookdeck/webhook-skills --skill bump-sh-webhooks
When to Use This Skill
- How do I receive Bump.sh webhooks?
- How do I verify the
X-Bump-Signature-256signature on a Bump.sh webhook? - How do I react when Bump.sh detects a structure change in my API documentation?
- Why is my Bump.sh webhook signature verification failing?
- Where do I find the Bump.sh webhook secret token?
Verification (core)
Bump.sh signs the raw request body with HMAC-SHA256, keyed on the webhook's secret token, and sends the lowercase hex digest in X-Bump-Signature-256 as sha256=<hex>. Nothing else is signed (no timestamp or id), so there is no replay window to check. Use the secret as UTF-8 bytes as-is, verify over the raw bytes before parsing, validate the digest's format, then compare in constant time. A bare 64-character hex value (no prefix) is also accepted, since the API reference shows one.
Node:
const crypto = require('crypto');
function verify(rawBody /* Buffer */, header, secret) {
if (!secret || typeof header !== 'string') return false;
const sig = header.startsWith('sha256=') ? header.slice(7) : header;
if (!/^[0-9a-fA-F]{64}$/.test(sig)) return false; // exact length + alphabet
const expected = crypto.createHmac('sha256', secret).update(rawBody).digest();
const received = Buffer.from(sig, 'hex'); // safe: already validated
return received.length === expected.length && crypto.timingSafeEqual(received, expected);
}
Python:
import hashlib, hmac, re
from typing import Optional
def verify(raw_body: bytes, header: Optional[str], secret: str) -> bool:
if not secret or not header:
return False
sig = header.removeprefix("sha256=")
if not re.fullmatch(r"[0-9a-fA-F]{64}", sig):
return False
expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).digest()
return hmac.compare_digest(bytes.fromhex(sig), expected)
A missing, empty, malformed or mismatched signature gets 401.
For complete handlers with route wiring, payload handling, and tests, see:
Webhook Payload
Bump.sh has one webhook: it is sent when a deployment changes the structure of a documentation. There is no event-name field or header to switch on. The body is JSON {api, diff}.
| Field | Meaning |
|---|---|
api | The documentation the change belongs to |
diff | The structural change Bump.sh detected |
The page linked from the Bump.sh webhook docs describes the payload in detail; treat every field as untrusted and check its type before reading into it. See references/overview.md.
Important Headers
| Header | Description |
|---|---|
X-Bump-Signature-256 | sha256= + hex HMAC-SHA256 of the raw body |
Environment Variables
BUMP_SH_WEBHOOK_SECRET=your_secret_token # Shown on the webhook's confirmation screen (Integrations tab)
Local Development
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 bump-sh --path /webhooks/bump-sh
Hookdeck's Bump.sh source type verifies the same signature (HMAC SHA-256, x-bump-signature-256, hex) before forwarding to your handler.
Reference Materials
- references/overview.md - What Bump.sh webhooks are and the payload
- references/setup.md - Registering a webhook and finding the secret token
- references/verification.md - Signature verification details and gotchas