Security
Protect your API keys, verify incoming webhooks and authenticate deliveries.
API key security
- Keep keys out of source code: read them from environment variables or a secret manager
- Never commit
.envfiles that contain keys - Use one key per service and environment, with the lowest role that works and project scoping
- Revoke keys that may have been exposed, and when people leave the team
Protect the ingest URL
The ingest endpoint accepts requests without authentication, so anyone who knows a buffer's ingest URL can send to it (and use your credits). Share it only with the sender and, when the sender can sign requests, enable source verification.
Verify incoming webhooks
Source verification makes Webbu reject requests that aren't signed with a secret you share with the sender. Configure it on the buffer (dashboard: Source Verification section):
{
"sourceVerification": {
"enabled": true,
"signingSecret": "your-shared-secret",
"signatureHeader": "x-webhook-signature",
"algorithm": "hmac-sha256"
}
}The sender must put, in signatureHeader, the lowercase hex HMAC-SHA256 of the JSON body, with no prefix. Webbu computes it over the compact JSON serialization of the parsed body (no whitespace, keys in the order received), so the sender should sign exactly the compact JSON it sends:
import { createHmac } from 'node:crypto';
const body = JSON.stringify({ event: 'order.created', customerId: 'cus_001' });
const signature = createHmac('sha256', process.env.WEBBU_SOURCE_SECRET!).update(body).digest('hex');
await fetch('https://webbu.dev/api/v1/ingest/p_shop/b_orders', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'x-webhook-signature': signature },
body,
});Requests without the header get 401 Missing signature header; a wrong signature gets 401 Invalid signature. Signatures are always checked with HMAC-SHA256, whatever algorithm says.
This format suits senders you control. Provider-specific signatures such as Stripe's Stripe-Signature, GitHub's X-Hub-Signature-256 (sha256= prefix) or Shopify's base64 X-Shopify-Hmac-Sha256 are not compatible, so leave source verification off for those. Webbu forwards the parsed payloads, not the original requests, so those signatures can't be checked at your destination either.
Verify deliveries from Webbu
Two ways to let your endpoint know a request comes from Webbu:
Static header. Add a secret to delivery.headers and check it in your endpoint:
{ "delivery": { "url": "https://your-app.example.com/webhooks/batch", "headers": { "Authorization": "Bearer your-destination-token" } } }Request signing. Enable signing on the buffer (dashboard: Delivery Configuration → Enable Request Signing (HMAC-SHA256)):
{ "delivery": { "signing": { "type": "hmac-sha256", "secret": "your-signing-secret", "header": "x-webbu-signature" } } }Each delivery then carries the lowercase hex HMAC-SHA256 of the raw request body in that header (x-webbu-signature by default). Verify it against the raw body, before parsing:
import { createHmac, timingSafeEqual } from 'node:crypto';
function isFromWebbu(rawBody: Buffer, signature: string | undefined): boolean {
if (!signature) return false;
const expected = createHmac('sha256', process.env.WEBBU_SIGNING_SECRET!).update(rawBody).digest('hex');
return signature.length === expected.length && timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}Transport
The API and ingest endpoint are served over HTTPS only. Use an https:// destination URL so batches are encrypted in transit as well.