Skip to main content

Webhooks

Webhooks let your integrations take action in response to events that occur in Eppo.

Experiment Webhook Events

This webhook is a good solution when a custom application needs to display or take action on the most up to date state of an experiment.

The webhook sends four types of experiment update events. If you only want to take action based on certain types of events, you can filter to just the events you are interested in subscribing to based on their event type in the request body.

Experiment Metric Updated

Triggers when:

  • Metric is added or removed
  • Metric collection is added or removed

Request body:

{
"event": "experiment.metric.updated",
"data": {
"experiment_id": "<experiment_id>",
"experiment_key": "<experiment_key>"
},
"signature": "<signature>"
}

Experiment Configuration Updated

Triggers when:

  • User edits any configuration

Request body:

{
"event": "experiment.configuration.updated",
"data": {
"experiment_id": "<experiment_id>",
"experiment_key": "<experiment_key>"
},
"signature": "<signature>"
}

Experiment Status Updated

Triggers when:

  • Experiment's status changes

Request body:

{
"event": "experiment.status.updated",
"data": {
"experiment_id": "<experiment_id>",
"experiment_key": "<experiment_key>"
},
"signature": "<signature>"
}

Experiment Calculated Metrics Updated

Triggers when:

  • Data pipeline run irrespective of success or failure and mode of trigger manual or scheduled

Request body:

{
"event": "experiment.calculated_metrics.updated",
"data": {
"experiment_id": "<experiment_id>",
"experiment_key": "<experiment_key>",
"meta_data": {
"status": "<success | failure>",
"is_manual_refresh": "<boolean>",
"is_data_updated": "<boolean>",
"time_taken_seconds": "<number>",
"is_traffic_imbalance": "<boolean>",
"assignments_scan_start_date": "<date>",
"assignments_scan_end_date": "<date>"
}
},
"signature": "<signature>"
}

Flagging Webhooks

The flagging webhook is a good solution when a custom application needs to display or take action on the most up to date state of a flag.

Flag Configuration Updated

This webhook is sent when a flag or its associated models, such as assignments, targeting rules, environments or audiences, are updated.

In short, any operation visible in the Flag History is sent to the webhook.

Request body:

{
"event": "flag.configuration.updated",
"data": {
"flag": {
"id": "<flag_id>",
"key": "<flag_key>"
}
},
"signature": "<signature>"
}

Configuring the webhook

To use the webhook, you first need to setup a URL on your side to receive the webhook payload.

The configuration is done in the Admin > Integrations page.

Once that is done, contact Eppo support to customize the webhook to your needs.

Webhook Signature

The webhook payload is signed with a signature. The signature is a hash of the payload and the webhook secret.

Integrating and Verifying the Signature

To verify the webhook signature, you'll need to:

  1. Get the signature from the webhook payload
  2. Generate a HMAC SHA-256 hash of the raw request body using your webhook secret
  3. Compare the generated hash with the received signature

Here's an example in TypeScript/Node.js:

import crypto from 'crypto';

function generateHMACSignature(secret: string, payload: string): string {
return crypto.createHmac('sha256', secret)
.update(payload)
.digest('hex');
}

function isValidWebhookSignature(
payload: string,
signature: string,
webhookSecret: string
): boolean {
const expectedSignature = generateHMACSignature(webhookSecret, payload);
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}

// Example usage in an Express route handler
app.post('/webhook', (req, res) => {
const signature = req.body.signature;
const payload = JSON.stringify(req.body);
const webhookSecret = process.env.WEBHOOK_SECRET;

if (!isValidWebhookSignature(payload, signature, webhookSecret)) {
return res.status(401).send('Invalid signature');
}

// Process the webhook
// ...
});
note

Always use a constant-time comparison function (like crypto.timingSafeEqual) when comparing signatures to prevent timing attacks.