Agent skill
Bolt Webhooks Skill
Receive and verify Bolt checkout (boltapp.com) webhooks. Use when setting up Bolt webhook handlers, debugging X-Bolt-Hmac-Sha256 signature verification, or handling transaction events like payment, capture, credit, void, auth, pending, and rejected_irreversible.
Install this skill
npx skills add hookdeck/webhook-skills --skill bolt-webhooks
Bolt here is the Bolt checkout and payments platform (boltapp.com), not Bolt ride-hailing or bolt.new.
When to Use This Skill
- How do I receive Bolt webhooks?
- How do I verify the
X-Bolt-Hmac-Sha256signature on a Bolt webhook? - How do I handle Bolt
payment,capture,credit,void, orrejected_irreversibleevents? - Why is my Bolt webhook signature verification failing?
- Why does Bolt keep retrying my webhook?
Verification (core)
Bolt signs the raw request body with HMAC-SHA256, keyed with your Signing Secret, and sends the result base64-encoded in X-Bolt-Hmac-Sha256. There is no timestamp and no signature prefix. The Signing Secret (Merchant Dashboard > Administration > API > Signing Secret) is used as a raw string.
Node:
const crypto = require('crypto');
function verifyBoltWebhook(rawBody, hmacHeader, secret) {
if (!hmacHeader || !secret) return false;
const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('base64');
try {
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(hmacHeader));
} catch {
return false; // different lengths
}
}
Python:
import base64, hashlib, hmac
def verify_bolt_webhook(raw_body: bytes, hmac_header: str, secret: str) -> bool:
if not hmac_header or not secret:
return False
expected = base64.b64encode(
hmac.new(secret.encode(), raw_body, hashlib.sha256).digest()
).decode()
return hmac.compare_digest(expected.encode(), hmac_header.encode())
Bolt does not offer an SDK for receiving or verifying webhooks, so verification is manual in every framework. Verify before parsing JSON: re-serializing changes the bytes and breaks the signature.
For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.
Common Event Types
The event type is the top-level type field of the JSON body (the object is transaction; credit_card_deleted has object credit_card).
| Event | Description |
|---|---|
pending | Pre-authorization succeeded; transaction is in fraud review |
failed_payment | Payment failed pre-authorization |
payment | Automatic capture: passed authorization and fraud review, funds captured |
auth | Manual capture: authorized, ready for you to capture |
capture | A manual capture succeeded |
credit | A refund or credit was processed |
void | The transaction was voided |
rejected_irreversible | Failed fraud review; cannot be appealed |
rejected_reversible | Flagged in fraud review; a re-review can be requested |
risk_insights | Risk information from the fraud review is available |
newsletter_subscription | Customer subscribed to the merchant's newsletter |
credit_card_deleted | Customer removed a saved card (beta, custom cart) |
Subscription events (subscription_created, subscription_renewed, ...) exist too. Acknowledge event types you don't process. See references/overview.md.
Handler Notes
- Respond HTTP 200 with a valid JSON body (e.g.
{"received": true}). Any other status, or a non-JSON body, makes Bolt retry with exponential back-off. - Payloads carry no event ID, so make handlers idempotent on
type+data.id/data.reference. - Webhooks are separate from Merchant Callbacks and are configured under Administration > Developers > Webhooks.
Environment Variables
BOLT_SIGNING_SECRET=your_signing_secret # Merchant Dashboard > Administration > API > Signing Secret
Local Development
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 bolt --path /webhooks/bolt
Reference Materials
- references/overview.md - Bolt webhook concepts, events, payload fields
- references/setup.md - Dashboard and API configuration, Signing Secret
- references/verification.md - Signature verification details and gotchas