Webhooks
Receive real-time notifications when events occur in your experiments
Prerequisites: You need a project created and a publicly accessible HTTPS endpoint to receive webhook events.
Overview
Webhooks allow you to receive HTTP POST requests to your server whenever specific events occur in LaikaTest. Use webhooks to trigger automated workflows, update external systems, or build custom integrations.
Subscribe to experiment lifecycle events
HMAC signatures verify payload authenticity
Supported Events
Subscribe to any combination of the following event types:
| Event Type | Description |
|---|---|
experiment.started | Fired when an experiment begins running |
experiment.paused | Fired when an experiment is paused |
experiment.completed | Fired when an experiment finishes |
experiment.status_changed | Fired on any experiment status change |
test.ping | Test event for verifying your endpoint |
Creating a Webhook
Follow these steps to set up a webhook in your project:
- 1. Navigate to Settings → Integrations → Webhooks
- 2. Click "Add Webhook"
- 3. Enter your webhook URL (must be HTTPS)
- 4. Your endpoint must respond to the verification challenge
- 5. Configure the webhook name and select events to subscribe
- 6. Copy and securely store the webhook secret (shown only once)
URL Verification
Before a webhook is created, LaikaTest verifies your endpoint by sending a challenge request. Your server must echo back the challenge value.
Challenge Request
{ "type": "url_verification", "challenge": "abc123xyz789"}Expected Response
{ "challenge": "abc123xyz789"}Example Handler
import express from 'express';const app = express();app.use(express.json());app.post('/webhooks/laikatest', (req, res) => { // Handle URL verification challenge if (req.body.type === 'url_verification') { return res.json({ challenge: req.body.challenge }); } // Handle actual webhook events const { event_type, data, timestamp } = req.body; console.log(`Received ${event_type} at ${timestamp}`); // Process the event... res.status(200).send('OK');});Webhook Payload
When an event occurs, LaikaTest sends a POST request with the following structure:
{ "event_type": "experiment.completed", "timestamp": "2026-01-23T12:00:00.000Z", "webhook_id": "wh_abc123", "data": { "experiment_id": "exp_xyz789", "project_id": "proj_def456", "old_status": "running", "new_status": "completed", "experiment": { "id": "exp_xyz789", "name": "Homepage CTA Test", "status": "completed", "traffic_percentage": 100, "variants": [...] } }}Verifying Signatures
Every webhook request includes signature headers to verify the payload authenticity. Always verify signatures in production.
Signature Headers
| Header | Description |
|---|---|
X-Webhook-Signature | HMAC-SHA256 signature of the payload |
X-Webhook-Timestamp | Unix timestamp when the request was sent |
X-Webhook-Event | The event type (e.g., experiment.completed) |
Signature Verification
The signature is computed as: HMAC-SHA256(timestamp + "." + payload, secret)
import crypto from 'crypto';function verifyWebhookSignature( payload: string, signature: string, timestamp: string, secret: string): boolean { const signedPayload = `${timestamp}.${payload}`; const expectedSignature = crypto .createHmac('sha256', secret) .update(signedPayload) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(expectedSignature) );}// In your webhook handlerapp.post('/webhooks/laikatest', (req, res) => { const signature = req.headers['x-webhook-signature'] as string; const timestamp = req.headers['x-webhook-timestamp'] as string; const payload = JSON.stringify(req.body); if (!verifyWebhookSignature(payload, signature, timestamp, WEBHOOK_SECRET)) { return res.status(401).send('Invalid signature'); } // Process verified webhook...});Important: Always use constant-time comparison (like timingSafeEqual or hmac.compare_digest) to prevent timing attacks.
Webhook Status
Webhooks have one of four status states:
Webhook created but URL not yet verified
Webhook is verified and receiving events
Recent deliveries have failed
Auto-disabled after 10 consecutive failures
Note: Webhooks are automatically disabled after 10 consecutive delivery failures. Re-enable them from the settings page after fixing the endpoint issue.
Best Practices
- Respond quickly: Return a 2xx response within 30 seconds. Process events asynchronously if needed.
- Verify signatures: Always verify the webhook signature in production to ensure requests are from LaikaTest.
- Handle duplicates: Use the
webhook_idandtimestampto deduplicate events if needed. - Store secrets securely: Keep your webhook secret in environment variables, never in code.
- Monitor deliveries: Check the delivery logs in the dashboard to debug failed webhooks.
- Use HTTPS: Webhook URLs must use HTTPS for secure transmission.
Testing Webhooks
Use the "Test" button in the webhook settings to send a test event to your endpoint. This sends a test.ping event with sample data.
For local development, use tools like ngrok or webhook.site to expose your local server.