Skip to Content

List webhooks

GET /webhooks

Response 200

[ { "id": "wh_abc123", "url": "https://myapp.com/webhooks/canarygate", "events": ["flag.enabled", "flag.disabled"], "active": true, "createdAt": "2025-01-01T00:00:00Z" } ]

Create webhook

POST /webhooks

Body

{ "url": "https://myapp.com/webhooks/canarygate", "events": ["flag.enabled", "flag.disabled", "flag.updated"] }

Response 201

{ "id": "wh_abc123", "url": "https://myapp.com/webhooks/canarygate", "events": ["flag.enabled", "flag.disabled", "flag.updated"], "secret": "whsec_xxxxxxxxxxxxxxxx", "active": true }

The secret field is returned only on creation. Store it in an environment variable — it cannot be retrieved afterwards.

Update webhook

PATCH /webhooks/:id

Body (optional fields)

{ "active": false, "events": ["flag.enabled"] }

Delete webhook

DELETE /webhooks/:id

Response 204 — no body.

Validating the signature

Each webhook request includes the X-Canarygate-Signature header:

import { createHmac, timingSafeEqual } from 'crypto' export function verifyWebhookSignature( rawBody: string, signature: string, secret: string ): boolean { const expected = `sha256=${createHmac('sha256', secret) .update(rawBody) .digest('hex')}` return timingSafeEqual(Buffer.from(signature), Buffer.from(expected)) }

Use timingSafeEqual to prevent timing attacks.

Last updated on