Apr 2026
A webhook that fires once and forgets is fine in a demo and a liability in production. Endpoints time out, deploy, rollback, rate-limit, or just plain disappear. If you need to know when a run finishes, 'send the event once' is not sufficient — you need retries.
BrowserPilot does not give you a choice: every run event (start, step, complete, fail) is signed with HMAC-SHA256 using your endpoint secret. It's authenticated. And it's retried with exponential backoff (5s, 10s, 30s, 60s, 300s) until your endpoint acknowledges it with a 2xx status code.
This means your endpoint will see some events more than once. That is not a bug, it is a feature — it is the price of reliability. Your handler needs to be idempotent: keyed on run id plus event type, so redeliveries are harmless. Log the run id, check the signature, do the work idempotently, return success.
Fan-out means one run can notify your backend, a Slack relay, and a data pipeline at once — each with its own delivery log and retry schedule. You can add or remove endpoints without changing anything else. Each endpoint has its own backoff timer, so if your Slack webhook is down, your backend still gets the data.
The full delivery log is visible in the dashboard: every retry attempt, every status code, every failure. If an event did not arrive, you can see exactly where and why. If your handler was down for an hour and you missed events, you can replay them.
Signing the payload means you can trust it. Verifying the signature is a few lines of code: grab the timestamp and signature from the headers, reconstruct the signed content, compute HMAC-SHA256 with your secret, compare. If the signatures do not match, discard the request. That is your only defense against someone spoofing a run completion and breaking your workflow.