Agent skill
Bringg Webhooks Skill
Receive and authenticate Bringg delivery orchestration webhooks. Use when setting up a Bringg webhook endpoint, securing it with Static Headers authentication, debugging 401s on Bringg webhooks, or handling webhook_type events such as task_created, task_done, task_cancelled, driver_assigned, way_point_arrived and note_created.
Install this skill
npx skills add hookdeck/webhook-skills --skill bringg-webhooks
Bringg POSTs JSON to your URL when an order, driver or route event occurs. Bringg webhooks are not signed: there is no HMAC and no timestamp. You authenticate them with a secret header that you add to the webhook as a Static Header (a Key-Value pair), and you route them by the webhook_type field in the body.
When to Use This Skill
- How do I receive Bringg webhooks?
- How do I authenticate Bringg webhooks with Static Headers?
- Does Bringg sign webhook requests? (No: use a secret header)
- How do I handle
task_created,task_doneordriver_assignedevents? - Why does my Bringg webhook endpoint return 401?
Verification (core)
The header name is whatever Key you chose, so read it from config. Compare the whole header value (including any Bearer prefix you typed) in constant time. Don't parse or strip it.
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 verifyBringgRequest(headers, config = process.env) {
const secret = config.BRINGG_WEBHOOK_SECRET;
if (!secret) return false; // never accept when unconfigured
const name = (config.BRINGG_WEBHOOK_HEADER || 'Authorization').toLowerCase();
const received = headers[name]; // Node lowercases header names
return typeof received === 'string' && received !== '' && safeEqual(received, secret);
}
Python: hmac.compare_ (bytes on both sides; str raises on non-ASCII). Return 401 on a missing header or mismatch, 400 for a body that isn't a JSON object, 200 once handled. Read the body raw (express.raw({ type: '*/*' }) in Express) so any content type works, and parse JSON only after the credential check.
A static shared credential authenticates the sender, not the body, and gives no replay protection (no signature, no timestamp). Use HTTPS only, and rotate the credential in Bringg if it leaks. Bringg also supports JWT and OAuth 2.0 authentication for webhooks; those need custom code and are not covered here.
For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.
Event Types
Every body has a webhook_type. The examples handle:
webhook_type | Sent When |
|---|---|
task_created | A new order is created |
task_done | An order is completed |
task_cancelled | An order is cancelled |
driver_assigned | An order is assigned to a driver |
way_point_arrived | A driver arrives at a way point (destination) |
note_created | A note, photo, signature or form is added to an order (Order Attachment Created) |
See references/overview.md for more events and the Webhooks Index link.
Environment Variables
BRINGG_WEBHOOK_HEADER=Authorization # Key of the Static Header (case-insensitive)
BRINGG_WEBHOOK_SECRET=Bearer replace-with-token # exact whole Value, including any "Bearer "
Local Development
Bringg can't reach localhost. Tunnel with the Hookdeck CLI (no account required):
npx hookdeck-cli listen 3000 bringg --path /webhooks/bringg
Use the printed URL as the webhook URL in Bringg and add your static header there.
Resources
- references/overview.md - How Bringg webhooks work, events, payloads, retries
- references/setup.md - Register a webhook and add the Static Header in Bringg
- references/verification.md - Static Headers check, limits, debugging 401s
- examples/ - Runnable Express, Next.js and FastAPI handlers with tests