Guides
Webhooks
Signed event deliveries (Standard Webhooks) for sessions, machines, runs and feedback, with retries and redelivery.
Webhooks push events to your HTTPS endpoint so you do not have to poll.
Events
| Event | When |
|---|---|
session.ready | A session became ready |
session.failed | A session failed |
session.closed | A session closed |
worker.offline / worker.online | A machine stopped or resumed sending heartbeats |
run.completed | An automation run finished |
feedback.updated | One of your feedback tickets changed |
Create an endpoint
curl -X POST https://browlix.com/api/public/v1/webhooks \
-H "Authorization: Bearer $BROWLIX_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"command_id\":\"$(uuidgen)\",\"url\":\"https://example.com/browlix\",\"events\":[\"session.ready\",\"session.closed\"]}"The URL must be https:// on a public host name, on port 443, 2053, 2083, 2087, 2096 or 8443. The reply contains the signing secret (whsec_…) once; store it in your secret manager.
Verify every request
Each delivery carries webhook-id, webhook-timestamp and webhook-signature headers (Standard Webhooks v1). Verify the raw body before parsing it:
import { verifyWebhook, WebhookVerificationError } from "@browlix/sdk";
app.post("/browlix", express.text({ type: "application/json" }), async (req, res) => {
try {
const event = await verifyWebhook<{ id: string; type: string; data: unknown }>(
process.env.BROWLIX_WEBHOOK_SECRET!, req.headers, req.body,
);
await handleOnce(event); // a repeated webhook-id is the same event redelivered
res.sendStatus(204);
} catch (e) {
res.sendStatus(e instanceof WebhookVerificationError ? 400 : 500);
}
});Timestamps more than 5 minutes old or ahead are rejected. Handle each webhook-id once: retries and redeliveries reuse it.
Retries
A delivery that does not get a 2xx within the time limit is retried up to 8 attempts in total, after 1 minute, 5 minutes, 30 minutes, 2 hours, 5 hours, 10 hours and 10 hours. webhooks.deliveries lists attempts with status and duration; webhooks.redeliver sends a finished delivery again with the same webhook-id; webhooks.test sends one signed webhook.test event.
Rotating the secret
webhooks.rotate_secret returns a new secret once. For overlap_hours the old secret keeps signing too — each request carries both signatures — so your receiver can switch without missing events.
