Webhooks
Webhooks send real-time HTTP POST notifications to your URL when experiment events occur. Use them to integrate A vs B with Slack, CI/CD pipelines, data warehouses, monitoring tools, or any system that can receive HTTP requests.
Setting up a webhook
- Navigate to Organisation Settings → Integrations → Webhooks.
- Click Create Webhook.
- Enter a name(e.g. "Slack Notifications"), the HTTPS URL of your endpoint, and select which events to subscribe to.
- Click Create Webhook. Copy the signing secret shown — you will need it to verify webhook signatures.
- Click Send Test Ping from the webhook detail view to verify your endpoint is receiving requests.
Available events
| Event | Description |
|---|---|
experiment.launched | Experiment transitioned from draft to running |
experiment.paused | Running experiment was paused |
experiment.resumed | Paused experiment was resumed |
experiment.completed | Experiment was stopped / completed |
experiment.changes_published | Pending changes were published to a running experiment |
Payload format
Every delivery is an HTTP POST with Content-Type: application/json and the following headers:
| Header | Description |
|---|---|
X-AvsB-Delivery-Id | Unique delivery ID for deduplication |
X-AvsB-Event | Event type (e.g. experiment.launched) |
X-AvsB-Signature | HMAC-SHA256 signature: sha256=<hex> |
X-AvsB-Timestamp | ISO-8601 timestamp |
User-Agent | AvsB-Webhooks/1.0 |
Example payload body:
1{2 "id": "del_clxyz123abc",3 "event": "experiment.launched",4 "timestamp": "2026-04-12T14:30:00.000Z",5 "project": {6 "id": "clxyz456def",7 "shortId": 200001,8 "name": "Marketing Site"9 },10 "experiment": {11 "id": "clxyz789ghi",12 "shortId": 300001,13 "name": "New Checkout Flow",14 "status": "RUNNING",15 "previousStatus": "DRAFT"16 },17 "triggeredBy": {18 "id": "clxyzusr001",19 "name": "Jane Smith",20 "email": "jane@example.com",21 "role": "ADMIN"22 }23}Verifying signatures
Every webhook delivery includes an X-AvsB-Signatureheader containing an HMAC-SHA256 hex digest of the raw request body, computed using your webhook's signing secret. Always verify the signature before processing the payload.
1const crypto = require('crypto');2
3function verifySignature(rawBody, secret, signatureHeader) {4 const expected = 'sha256=' + crypto5 .createHmac('sha256', secret)6 .update(rawBody)7 .digest('hex');8 // Use timing-safe comparison to prevent timing attacks9 if (signatureHeader.length !== expected.length) return false;10 return crypto.timingSafeEqual(11 Buffer.from(signatureHeader),12 Buffer.from(expected)13 );14}15
16// In your Express handler — use express.raw() to get the raw body17// for signature verification (express.json() parses the body and18// loses the original bytes):19app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {20 const signature = req.headers['x-avsb-signature'];21 if (!verifySignature(req.body, process.env.WEBHOOK_SECRET, signature)) {22 return res.status(401).send('Invalid signature');23 }24 const event = JSON.parse(req.body.toString());25 console.log('Received:', event.event, event.experiment?.name);26 res.status(200).send('OK');27});Retry policy
If your endpoint does not respond with a 2xx status code within 10 seconds, A vs B will retry the delivery automatically:
- 1st retry — after 1 minute
- 2nd retry — after 5 minutes
- 3rd retry — after 30 minutes
After 3 failed attempts, the delivery is marked as Failed. You can manually retry failed deliveries from the delivery log.
Auto-disable
If a webhook has 5 consecutive events where all retry attempts fail, A vs B automatically disables the webhook to prevent wasting resources on a broken endpoint. The webhook detail view will show the reason for disabling.
To re-enable, fix your endpoint and toggle the webhook back on. This resets the failure counter.
Delivery log
The webhook detail view includes a delivery log showing all deliveries from the last 30 days. Each entry shows the event type, delivery status, HTTP response code, number of attempts, and timestamp. Click Retry on any failed delivery to re-queue it.
Secret rotation
If your signing secret is compromised, click Rotate in the webhook detail view to generate a new secret. In-flight deliveries will continue using the old secret; all new deliveries will use the new one. Update your endpoint with the new secret immediately.
Limits
- Maximum 10 webhooks per project
- Delivery timeout: 10 seconds
- Response body stored: first 1 KB (for debugging)
- Delivery log retention: 30 days
Troubleshooting
- Webhook creation fails with "URL must use HTTPS" — only HTTPS URLs are supported. Set up TLS on your endpoint or use a service like ngrok for testing.
- Test ping fails— check that your endpoint returns a 2xx status within 10 seconds. Check the delivery log for the response code and error message.
- Webhook was auto-disabled— your endpoint has been failing consistently. Fix the endpoint, then re-enable the webhook from the toggle switch.
- Duplicate events received — use the
X-AvsB-Delivery-Idheader or theidfield in the payload to deduplicate. Retries send the same delivery ID.