Webhooks
Receive HTTP callbacks when key events occur in your SimuTest tests.
Overview
Webhooks let you receive real-time notifications without maintaining a persistent connection. When an event occurs, SimuTest sends an HTTP POST request to your configured endpoint with a JSON payload describing the event.
Webhooks are ideal for CI/CD pipelines — use quality_gate.failed to block deployments and test.completed to trigger downstream workflows like report distribution or Slack notifications.
Note: Your endpoint must respond with a 2xx status code within 10 seconds. Timeouts and non-2xx responses trigger the retry policy.
Supported Events
| Event | Description |
|---|---|
| test.started | Test has been created and sessions are starting |
| test.progress | Periodic progress update (every 10% of sessions completed) |
| test.completed | All sessions finished; report is available |
| test.failed | Test encountered a fatal error and could not complete |
| quality_gate.passed | All scores met or exceeded the configured threshold |
| quality_gate.failed | One or more scores fell below the configured threshold |
Payload Format
All webhook payloads share a common envelope with event, test_id, timestamp, and a data object specific to the event type.
test.completed payload
{
"event": "test.completed",
"test_id": "test_abc123",
"timestamp": "2025-01-15T10:25:12Z",
"data": {
"url": "https://example.com",
"task": "Find and purchase the premium plan",
"sessions_total": 200,
"sessions_completed": 200,
"duration_seconds": 1512,
"aggregate_scores": {
"task_completion": 0.84,
"cta_findability": 0.79,
"overall": 0.82
},
"quality_gate": {
"passed": true,
"threshold": 0.75
},
"report_url": "https://app.simutest.dev/reports/rpt_def456",
"report_id": "rpt_def456"
}
}quality_gate.failed payload
{
"event": "quality_gate.failed",
"test_id": "test_abc123",
"timestamp": "2025-01-15T10:25:12Z",
"data": {
"threshold": 0.80,
"score": 0.72,
"failed_criteria": ["task_completion", "cta_findability"],
"report_url": "https://app.simutest.dev/reports/rpt_def456"
}
}Security
Every webhook delivery includes an X-SimuTest-Signature header. The value is an HMAC-SHA256 signature of the raw request body using your webhook secret, prefixed with sha256=.
Always verify the signature before processing the payload. Use a timing-safe comparison to prevent timing attacks.
import crypto from 'crypto';
function verifyWebhook(
payload: string,
signature: string,
secret: string
): boolean {
const expected = crypto
.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('hex');
const trusted = Buffer.from(`sha256=${expected}`, 'ascii');
const received = Buffer.from(signature, 'ascii');
return crypto.timingSafeEqual(trusted, received);
}
// Express handler
app.post('/webhooks/simutest', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-simutest-signature'] as string;
const isValid = verifyWebhook(req.body.toString(), signature, process.env.WEBHOOK_SECRET!);
if (!isValid) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body.toString());
// Handle event...
res.status(200).send('OK');
});Retry Policy
If your endpoint fails to respond with a 2xx status within 10 seconds, SimuTest will retry with exponential backoff:
| Attempt | Delay |
|---|---|
| 1st retry | 5 seconds |
| 2nd retry | 30 seconds |
| 3rd retry | 5 minutes |
| After 3rd failure | Delivery abandoned; webhook is disabled after 10 consecutive failures |
Delivery attempts and their status are visible in the Settings → Webhooks dashboard. You can manually replay any delivery from the last 72 hours.
Configuration
Configure webhooks from the Settings → Webhooks page in the dashboard, or via the API:
curl -X POST https://api.simutest.dev/v1/webhooks \
-H "Authorization: Bearer st_live_abc123..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourapp.com/webhooks/simutest",
"events": ["test.completed", "quality_gate.failed"],
"secret": "whsec_your_random_secret"
}'Omit the events array to subscribe to all events. Set a unique secret for each endpoint — SimuTest will use it to sign all deliveries to that URL.
On this page