Webhook Delivery
When a prediction reaches a terminal state, each::labs fires off an HTTP POST to your configuredwebhook_url. Webhooks fire only on completion or failure — there are no webhooks for intermediate states, and cancellations do not trigger one.
- Method:
POST - Content-Type:
application/json - Expected response: any
2xxstatus to acknowledge receipt;4xx/5xxresponses trigger a retry
Payload Structure
Webhook payloads use a compact two-value status vocabulary:succeeded or failed. This differs from the richer lifecycle you see when polling — use Get Prediction if you need the full six-state view (created, starting, processing, success, error, cancelled).
Prediction Succeeded
exec_id— the prediction ID you received from Create Predictionflow_id— the workflow ID when the prediction was triggered by a workflow, otherwisenulloutput— the prediction output; its shape depends on the model (string, array, or object)
Prediction Failed
output is an array wrapping the error detail: read output[0].error for the failure reason. The top-level error field is always an empty string.
Webhook Handler Examples
Security
Verifying Deliveries
If you set awebhook_secret when creating your prediction, each::labs signs every delivery for that prediction. Signed deliveries carry two extra headers:
X-Webhook-Signature—sha256=followed by a lowercase hex HMAC-SHA256 over<X-Webhook-Timestamp>.<raw request body>X-Webhook-Timestamp— Unix time in seconds at which the delivery was signed
X-Webhook-Secret header. That header predates signing and is still sent so receivers built against it keep working, but prefer the signature: it proves the body was not modified, which comparing the header cannot.
Verify against the raw bytes of the request body. The handler examples above call
await request.json() and read req.body, which is fine once a delivery is verified — but a parsed-and-re-serialized body produces a different signature. Capture the raw body first.Retry Behavior
Deliveries are attempted up to 3 times in total: the initial attempt plus 2 retries, spaced roughly 10 seconds apart. Retries stop after that. Use Get Webhook to check out the full delivery history.Best Practices
- Return
2xxas fast as you can, then process data asynchronously - Implement idempotency, since you may receive the same webhook more than once
- Log incoming payloads for debugging
- Set a
webhook_secretand verify the signature on every delivery - Set up monitoring for your webhook endpoint’s availability