Webhooks API
Register project webhook endpoints and inspect signed-delivery attempts.
All routes require Authorization: Bearer <project-api-key>. Because endpoints receive project-wide execution events, user-pinned keys receive 403 auth_insufficient_scope.
Create an endpoint
POST /v1/webhooks
{
"url": "https://example.com/webhooks/eyeball",
"events": ["execution.completed", "voice.session.event"],
"active": true
}The 201 response includes endpointId, normalized url, events, active, createdAt, updatedAt, secretPrefix, and the complete secret. The complete secret appears only in this response.
Supported subscriptions are execution.completed, execution.succeeded, execution.failed, execution.cancelled, voice.session.event, voice.transcript.ready, voice.observer.failed, trigger.*, and exact canonical trigger event types such as trigger.slack.message_received. The execution.completed selector matches all three terminal execution events.
voice.observer.failed is an executor-owned terminal observation signal, not a worker-sequenced lifecycle event. Its data contains sessionId, pinned agentId/agentRevision, lastHandledSequence, attempts, reason (retry_exhausted or non_retryable), a safe observer operation, and a normalized public error. It does not alter the worker-owned session state; use the stable webhook event ID for receiver deduplication.
List and get endpoints
GET /v1/webhooks?limit=100&cursor=...returns{ webhooks, nextCursor? }.GET /v1/webhooks/:endpointIdreturns one endpoint or404.
List and get responses never include secret.
Update an endpoint
PATCH /v1/webhooks/:endpointId accepts any non-empty combination of url, events, and active. The response contains the updated endpoint without its signing secret. Every attempt resolves the endpoint's current URL, secret, and active state, so a URL change affects the next attempt and deactivation prevents unfinished delivery work from continuing rather than pausing it.
Rotate a signing secret
POST /v1/webhooks/:endpointId/rotate-secret replaces the signing secret immediately. The response includes the new secret and secretPrefix; the complete secret appears only in this rotation response. Every attempt, including a retry that is already queued, resolves the current secret and uses the replacement. The previous secret is invalid as soon as rotation succeeds.
Delete an endpoint
DELETE /v1/webhooks/:endpointId returns 204 or 404. Deletion prevents new scheduling and unfinished delivery work from continuing. It does not rewrite stored historical rows, but endpoint-scoped delivery history is no longer accessible through the public route after deletion.
Inspect deliveries
GET /v1/webhooks/:endpointId/deliveries?limit=100&cursor=... returns { deliveries, nextCursor? }. Each delivery includes:
deliveryId,eventId,eventType, andendpointId;status:pending,delivering,succeeded, orfailed;- append-only attempts with timestamps, response status code, or a sanitized transport error;
nextRetryAtwhile another attempt is scheduled andcompletedAtafter success or give-up.
Delivery responses are metadata-only. They never include the delivered payload, signing secret, request or receiver response body, or receiver headers.
The project Webhooks screen in the dashboard exposes endpoint CRUD, event selection, reveal-once create and rotation secrets, confirmed destructive actions, and this metadata-only delivery history. It uses the selected project's executor path in both demo and cloud mode.
Read Webhooks for signature verification, event envelopes, retries, ordering, and production durability requirements.