Webhooks
Webhooks notify external services when resources are created, updated, or deleted. EdgeFlags delivers webhook payloads via HTTP POST with optional HMAC signature verification.
Creating a webhook
curl -X POST \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "url": "https://your-service.com/webhooks/edgeflags", "secret": "whsec_your_signing_secret", "events": ["flag.created", "flag.updated", "flag.deleted"] }' \ "https://edgeflags.net/api/v1/webhooks"Required fields
| Field | Type | Description |
|---|---|---|
url | string | HTTPS endpoint to receive webhook payloads |
events | string[] | Event types to subscribe to |
Optional fields
| Field | Type | Description |
|---|---|---|
secret | string | Signing secret for HMAC verification |
URL restrictions
Webhook URLs must meet these requirements:
- HTTPS only — HTTP URLs are rejected
- No private IPs —
localhost,127.0.0.1,::1,0.0.0.0, RFC 1918 addresses (10.x,172.16-31.x,192.168.x), and169.254.xare blocked - No internal hostnames — domains ending in
.localor.internalare rejected
Event types
| Event | Triggered when |
|---|---|
flag.created | A new flag is created |
flag.updated | A flag is updated (including environment overrides) |
flag.deleted | A flag is deleted |
config.created | A new config is created |
config.updated | A config is updated |
config.deleted | A config is deleted |
segment.created | A new segment is created |
segment.updated | A segment is updated |
segment.deleted | A segment is deleted |
token.created | A new token is created |
token.deleted | A token is deleted |
project.updated | Project settings are updated |
Webhook payload
{ "event": "flag.updated", "resource": "new_checkout", "environment": "production", "data": { "enabled": true, "value": false, "version": 3 }, "timestamp": "2026-01-15T10:30:00.000Z"}HMAC signature verification
When a secret is configured, EdgeFlags signs each payload with HMAC-SHA256 and includes the signature in the X-Webhook-Signature header.
The signature is the hex-encoded HMAC-SHA256 of the raw JSON payload body using the secret as the key.
Verifying signatures
import { createHmac } from 'crypto';
function verifySignature(payload, signature, secret) { const expected = createHmac('sha256', secret) .update(payload) .digest('hex'); return expected === signature;}
// In your webhook handlerapp.post('/webhooks/edgeflags', (req, res) => { const signature = req.headers['x-webhook-signature']; const rawBody = JSON.stringify(req.body);
if (!verifySignature(rawBody, signature, process.env.WEBHOOK_SECRET)) { return res.status(401).send('Invalid signature'); }
// Process the webhook console.log('Event:', req.body.event); res.status(200).send('OK');});Retry behavior
Failed deliveries are retried with exponential backoff:
- Immediate — first attempt
- 1 second — second attempt
- 4 seconds — third attempt
After 3 failed attempts, the delivery is abandoned and a warning is logged. Each attempt has a 5-second timeout.
Listing webhooks
curl -H "Authorization: Bearer $ADMIN_TOKEN" \ "https://edgeflags.net/api/v1/webhooks"Response (secrets are never returned):
{ "webhooks": [ { "id": "a1b2c3d4e5f6a7b8", "config": { "url": "https://your-service.com/webhooks/edgeflags", "has_secret": true, "events": ["flag.created", "flag.updated", "flag.deleted"] } } ]}Deleting a webhook
curl -X DELETE \ -H "Authorization: Bearer $ADMIN_TOKEN" \ "https://edgeflags.net/api/v1/webhooks/a1b2c3d4e5f6a7b8"