Events
Subscribe with
job.* to get every job event. job.created, job.started and job.progress are accepted when you
subscribe, but are not sent today.
Add a webhook
For every job of your organization: create it once. The answer includessigning_secret in full, this one
time; afterwards only its first 8 characters are shown.
Per-job webhooks
Addwebhooks to a job when only that job should call a URL. Each one gets its own signing_secret, returned in
full in the create answer under ad_hoc_webhooks, and masked afterwards.
ACTOR.RUN.SUCCEEDED is job.completed,
ACTOR.RUN.FAILED is job.failed, ACTOR.RUN.TIMED_OUT is job.timed_out and ACTOR.RUN.ABORTED is
job.cancelled.
A webhook URL must use HTTPS, reach a public address (private and internal addresses are refused), be at most 2,048
characters, and not end in .php, .asp, .aspx, .jsp or .cgi.
What we send
APOST with a JSON body and these headers:
A real
job.completed delivery from a test run on a local stack, headers and body. usageTotalUsd is a number;
its value is shown as "…" because the docs leave amounts out.
account.low_balance sends organization_id, balance, threshold, currency (USD), level (low, or zero
when the balance is used up) and timestamp. Each level is sent at most once a day.
Verify the signature
Compute the HMAC-SHA256 of the raw request body, before any JSON parsing, with your signing secret, and compare it with the header in constant time. Parsing and re-serialising the body changes the bytes and breaks the check.Answer fast, retry safely
- Answer with any
2xxwithin 10 seconds; the connection must open within 5. Do the work afterwards, for example from a queue. - Redirects are not followed: a
3xxcounts as a failure. - A failed delivery is retried up to 5 times, after 2, 4, 8, 16 and 32 minutes. A TLS certificate error is not retried.
- After 5 events in a row fail every retry, the webhook is turned off:
is_activebecomesfalseanddisabled_reasonsays why. Turn it back on withPATCH /api/v1/webhooks/{id}/and{"is_active": true}. - The same event can arrive twice. Use
X-Delivery-ID, or the job id and event, to process it once.
Test and inspect
test with the body {"event": "test", "timestamp": ..., "data": {"message": ...}}, signed
like any other.
event_type, status (pending, delivered or failed), response_status_code and
attempts. POST /api/v1/webhooks/deliveries/{id}/retry/ sends one again.