run.blocked: a run that stops for a CAPTCHA, an SMS code, or a final submit is held for ten minutes, and this is how someone finds out in time.
Events
Delivery
Each delivery is an HTTPPOST with content-type: application/json and a 10-second timeout. Every delivery to your org carries the org-level secret in the x-sente-secret header:
Webhook URLs must be
http(s) and must resolve to a public address. URLs pointing at loopback, private ranges, link-local, or cloud-metadata addresses are rejected at registration with 400, and re-checked immediately before every delivery in case DNS changed in between.Create a webhook
POST /v1/webhooks
Idempotent per (url, identity scope): re-posting the same url and scope returns the existing subscription with its event list replaced by the one you sent. Safe to call on every app start — and note that it replaces rather than merges, so always send the full list.
201 — the only response in the API that contains the secret:
List webhooks
GET /v1/webhooks
200 — no secret in list responses:
POST /v1/webhooks — the response returns the org secret again, and the existing subscription is reused rather than duplicated.
Delete a webhook
DELETE /v1/webhooks/:id
204 with no body. 404 {"error": "not found"} for an unknown id or another org’s subscription.
Payloads
message.received
GET /v1/messages/:id. channel is always email today.
run.blocked
Fired the moment a run parks for a human, and carrying everything a notifier needs to route someone to the gate:Every blocked run also emails the org’s operators the same dashboard link, using each user’s notification preference. The webhook is for your systems; the email is the “you walked away” backstop. The
sente watch CLI command is a third path — a desktop notifier.run.completed / run.failed
run.failed has the same shape with "status": "failed", the failure code in code/detail, and "result": null. Both fire exactly once, from whichever writer wins the terminal transition — including the timeout and worker-recovery paths, so a run that dies quietly still notifies.
appUrl is null when the run has no registration behind it. Note that the run payloads use code/detail at the top level, where the run object from GET /v1/runs/:id nests them under error.
Related
Webhooks guide
Endpoint setup, verification, and retries in practice.
Human takeover
What to do when
run.blocked arrives.Messages
Fetch the body after
message.received.