Prefer: respond-async) reaches a final state, or a workflow run makes progress, GEEKIDEA sends a POST to your webhook endpoints. Synchronous calls don’t send webhooks; their result is already in the response.
Create an endpoint
Create endpoints in the dashboard under Settings → Webhooks, or with an admin key:urlmust be https and publicly reachable; private and internal addresses are rejected.project_idlimits the endpoint to one project; leave it out to receive events for the whole organization.eventsdefaults to all events.- The response includes the signing
secret(whsec_…) once. If you lose it, rotate it.
Events
generation.* events, data is the same generation object that GET /v1/generations/{id} returns.
For workflow.waiting_input, workflow.budget_exceeded, workflow.completed, workflow.failed and workflow.cancelled, data is the run object that GET /v1/workflow_runs/{id} returns. For workflow.step.completed, data is a step event:
step is the step’s state when the event is sent; a step that stops for confirmation shows waiting_input.
Verify signatures
Webhooks are signed with Standard Webhooks, the same scheme OpenAI uses. Each request has the headerswebhook-id (the event ID), webhook-timestamp and webhook-signature. Verify with a Standard Webhooks library, or with the OpenAI SDK’s webhooks.unwrap, using your whsec_ secret.
Delivery and retries
- Respond with a
2xxwithin 15 seconds. Anything else counts as a failure. Redirects are not followed. - Failed deliveries are retried after 5 s, 30 s, 2 min, 10 min, 30 min, 1 h, 2 h, 4 h, 6 h and 8 h (about 22 hours in total), then marked
dead. You can resend any delivery. - Rarely, the same event is delivered twice. Deduplicate on
webhook-id. - Webhooks are notifications. The source of truth is
GET /v1/generations/{id}(orGET /v1/workflow_runs/{id}for workflows), so keep a polling fallback for jobs you don’t hear about.
