This page covers outbound delivery (Vetta → your server). Inbound email/SMS receiving lands on an identity’s message feed today; the agent wake from a stored inbound message is coming soon — see Inbound events.
The webhook endpoint object
string
Unique id (e.g.
whk_01H...).string
Your HTTPS URL that receives deliveries.
string[]
Event types to deliver (e.g.
session.idle, budget.exceeded).boolean
Whether the endpoint receives deliveries. Set via update; auto-disabled after sustained failures.
string
Creation timestamp.
Create an endpoint
POST /v1/webhooks → 201 Created. The signing secret is always minted server-side and returned once, on this response.
string
required
HTTPS URL to receive events.
string[]
required
Event types to subscribe to. Use
["*"] for all.Retrieve, list & delete
Delete response
Update an endpoint
PATCH /v1/webhooks/{id} → 200 OK. Change the url, subscribed events, or pause/resume delivery with enabled.
string
New HTTPS URL.
string[]
Replace the subscribed event types.
boolean
Set
false to pause delivery, true to resume.Send a test delivery
POST /v1/webhooks/{id}/test → 202 Accepted. Queues one signed delivery to the endpoint so you can prove your verifier works before a real event depends on it. It ignores the endpoint’s events filter — you asked for this one — and carries the type webhook.test, so a handler that switches on type can ignore it safely. A disabled endpoint is refused rather than queued.
Response
Rotate the signing secret
POST /v1/webhooks/{id}/rotate → 200 OK. Issues a new secret (shown once). During the overlap window, deliveries are signed with both the old and new secrets, so you can roll your verifier with zero missed events. When the window closes, only the new secret signs.
integer
How long both secrets stay valid. Defaults to
24; 24 is the max. Use 0 to cut over immediately.Response
Delivery payload
Each delivery is aPOST to your URL with a JSON body wrapping the event, plus signature headers.
Body
Signature verification
Each signature is an HMAC-SHA256 over{timestamp}.{raw_body} keyed by your endpoint secret, encoded as v1=<hex>. The scheme version (v1) lets us evolve the algorithm without breaking verifiers, and multiple signatures let a secret rotation overlap.
To verify:
- Read the raw request body (do not re-serialize it).
- Build the signed payload:
`${timestamp}.${rawBody}`. - Compute your own
v1HMAC-SHA256 and check it against any signature in the header (both secrets are valid during an overlap window). - Reject the delivery if the timestamp is too old (e.g. > 5 minutes).
Delivery log & redelivery
Every attempt is recorded. Inspect it, drill into one delivery, and manually resend.id your handler dedupes on is unchanged. It is recorded as a new delivery record with its own attempt count, which leaves the original attempt’s outcome intact in the log.
string
Delivery id.
string
The
evt_... id delivered.string
The event type.
string
pending, succeeded, or failed.integer
Number of attempts so far.
integer | null
HTTP status your server returned on the last attempt.
string | null
First bytes of your server’s response body, for debugging.
string | null
When the delivery first succeeded.
string | null
When the next retry is scheduled, if still pending.
Response
Delivery, retries & auto-disable
Respond2xx within 10 seconds to acknowledge; slower responses count as a timeout. Any non-2xx response or timeout is retried with exponential backoff over ~24 hours. Deliveries carry a stable id — dedupe on it, since a delivery may occasionally arrive more than once.
If an endpoint returns only failures for 24 hours, Vetta flips it to enabled: false and stops delivering. Fix your endpoint, re-enable it with update, and redeliver any missed events.
Inbound receivers
Three routes under/v1/webhooks/ point the other way: they are inbound receivers the platform exposes for a provider to call, not endpoints you register or invoke.
These take a provider signature, not your API key, and there is no CLI or SDK verb for them by design — a caller with an API key has a first-class route for everything these do. They are listed here so the route table has no unexplained entries, not because you should call them.
2xx on acceptance; an unverifiable payload is rejected without side effects and never reaches an agent.