For async basics (fire-and-forget, polling with
client.wait()), see
Runs.1. Add a Callback URL
PasscallbackUrl in the output field when creating a run:
runId. When the run completes, we’ll POST the result to your callback URL.
2. Build a Webhook Handler
Create an endpoint to receive the webhook POST:Your endpoint must be publicly accessible. For local development, use
ngrok or similar.
3. Webhook Payload
When a run finishes, we POST this JSON to your URL:| Field | Description |
|---|---|
runId | The run’s unique ID |
jobId | Internal job ID |
status | Final status (succeeded, failed, timed_out, canceled) |
result | The completion result with choices array |
error | Error details (when failed, otherwise null) |
tokens | Token counts (inputTokens, outputTokens, costCents) |
createdAt | When the run was created |
startedAt | When processing began |
completedAt | When the run finished |
Delivery Guarantees
Webhooks are delivered with:- Retries — Failed deliveries retry with exponential backoff
- Timeouts — We wait up to 30 seconds for your 2xx response
- Dead-letter queue — Exhausted retries are stored for inspection
- Idempotency — Include a unique ID in your handler to prevent duplicates
Best Practices
- Respond quickly — Return 2xx within 30 seconds, process async if needed
- Be idempotent — You may receive the same webhook twice
- Log payloads — Store raw payloads for debugging
- Validate origin — Check request headers (signature verification coming soon)