Skip to main content

Webhooks

Webhooks push consent events to your server in real time. ConsentForge sends an HTTP POST to your endpoint when consent is created, updated, expired, or reset.

Managing webhooks via API

Create a webhook endpoint

POST /api/v1/webhooks
Authorization: Bearer cf_api_live_YOUR_TOKEN
Content-Type: application/json

{
"property_id": "prop_abc",
"url": "https://your-server.com/webhooks/consentforge",
"events": ["consent.created", "consent.updated", "consent.expired"],
"active": true
}

Response:

{
"id": "wh_xyz789",
"property_id": "prop_abc",
"url": "https://your-server.com/webhooks/consentforge",
"events": ["consent.created", "consent.updated", "consent.expired"],
"active": true,
"secret": "whsec_live_xxxxxxxxxxxxxxxx",
"created_at": "2026-03-09T12:00:00Z"
}
warning

The secret field is only returned on creation. Store it securely — it is never returned again.

List webhooks

GET /api/v1/webhooks?property_id=prop_abc
Authorization: Bearer cf_api_live_YOUR_TOKEN

Update a webhook

PATCH /api/v1/webhooks/wh_xyz789
Authorization: Bearer cf_api_live_YOUR_TOKEN
Content-Type: application/json

{
"events": ["consent.created", "consent.updated"],
"active": false
}

Delete a webhook

DELETE /api/v1/webhooks/wh_xyz789
Authorization: Bearer cf_api_live_YOUR_TOKEN

Events

EventWhen it fires
consent.createdFirst consent decision recorded for a user on this property
consent.updatedUser revisits and changes their choices
consent.expiredConsent reaches its configured expiry date
consent.resetProperty-level consent reset applied (all users re-asked)
scan.completedA property scan finishes
scan.finding_addedA new script or cookie was found in a scan

Payload envelope

All webhook requests share the same outer envelope:

{
"event": "consent.created",
"delivery_id": "del_01HXX",
"timestamp": "2026-03-09T12:00:00Z",
"property_id": "prop_abc",
"data": { ... }
}
FieldDescription
eventThe event type
delivery_idUnique ID for this delivery — use for idempotency
timestampISO 8601 UTC timestamp when the event was generated
property_idThe property the event relates to
dataEvent-specific payload (see below)

Event payloads

consent.created / consent.updated

{
"event": "consent.created",
"delivery_id": "del_01HXX",
"timestamp": "2026-03-09T12:00:00Z",
"property_id": "prop_abc",
"data": {
"receipt_id": "rec_def456",
"policy_id": "pol_ghi789",
"policy_version": 3,
"banner_version": 7,
"choices": {
"necessary": true,
"analytics": true,
"marketing": false,
"functional": true
},
"region": "DE",
"user_agent_hash": "sha256:3a4f...",
"ip_hash": "sha256:8b2c..."
}
}

consent.expired

{
"event": "consent.expired",
"delivery_id": "del_01HYY",
"timestamp": "2026-03-09T12:00:00Z",
"property_id": "prop_abc",
"data": {
"receipt_id": "rec_def456",
"expired_at": "2026-03-09T12:00:00Z",
"reason": "policy_version_change"
}
}

scan.completed

{
"event": "scan.completed",
"delivery_id": "del_01HZZ",
"timestamp": "2026-03-09T12:00:00Z",
"property_id": "prop_abc",
"data": {
"scan_id": "scan_abc123",
"url": "https://example.com",
"findings_count": 14,
"new_findings_count": 2,
"duration_ms": 8420
}
}

Delivery and retries

ConsentForge expects a 2xx HTTP response within 10 seconds. If the response times out or returns a non-2xx status, delivery is retried with exponential backoff:

AttemptDelay
1 (initial)immediately
230 seconds
35 minutes
430 minutes
52 hours

After 5 failed attempts, the delivery is marked as failed and no further retries occur. You can manually retry from Dashboard → Property → Webhooks → Delivery Log.

Idempotency

Each delivery has a unique delivery_id. Retried deliveries reuse the same delivery_id. Store processed delivery IDs to avoid double-processing:

const processedIds = new Set(); // use a database in production

app.post('/webhooks/consentforge', (req, res) => {
const { delivery_id, event, data } = req.body;

if (processedIds.has(delivery_id)) {
return res.json({ status: 'duplicate' });
}

processedIds.add(delivery_id);
// process event...
res.json({ status: 'ok' });
});

Signature verification

See Webhook Security for how to verify the X-ConsentForge-Signature header.

Testing

Use the Send Test Event button in Dashboard → Property → Webhooks to send a sample payload to your endpoint. You can also use webhook.site to inspect requests during development.