BashBrainTeammatesPricingDevelopersGet a test key

Webhooks and events

Where events go, how each delivery went, and the record of every event.

Send Authorization: Bearer vk_test_... on every call.

RoutesOpen one for every field it takes and answers.

POST/v1/webhooksRegister a URL and the events it wants.

The signing secret is shown once.

Your API key, scope setup or all. On the card: events. Every call here is a checked sample.

Request4 fields

Body

urlstring (URL)requiredWhere to send the events: a public https URL, at most 2,048 characters. Private, local and internal addresses are refused.
Limits
At most 2048 characters.
Example
https://api.example.com/vestra
events(string | "*")[]requiredThe events it wants: 1 to 40 types, or * for all.
Limits
1 to 40 items.
descriptionstringA note for you, in at most 500 characters.
Limits
At most 500 characters.
activebooleanWhether to send to it. Default: true.
Default
true
Answers 20112 fields
idstringThe endpoint (whk_...).
Example
whk_2bq
object"webhook_endpoint"Always webhook_endpoint.
Type
"webhook_endpoint"
urlstringWhere the events go.
Type
string
events(string | "*")[]The events it wants.
Type
(string | "*")[]
descriptionstring | nullYour note; null when you gave none.
Type
string | null
activebooleanWhether events are sent to it.
Type
boolean
mode"live" | "test"The mode it hears: test or live, the mode of the key that made it. A test endpoint never hears a live event.
Type
"live" | "test"
deployment_idstring | nullOnly this deployment's events reach it (dep_...), plus your account's, such as keys, users and usage alerts. Set when a deployment's vestra.yaml declared the endpoint. Null: every event its types allow.
Type
string | null
managed_by"file" | nullfile: declared in that deployment's vestra.yaml, so deploying the file changes it; null: you made it.
Type
"file" | null
created_atstringWhen it was made, as an ISO 8601 time.
Type
string
updated_atstringWhen it last changed, as an ISO 8601 time.
Type
string
secretstringThe signing secret, shown this once: check every delivery against it (the Vestra-Signature header). Keep it on your server.
Example
whsec_...
TypeScript
const endpoint = await vestra.events.to('https://hooks.example.com/vestra');
Python
endpoint = vestra.events.to("https://hooks.example.com/vestra")
CLI
vestra events --to https://hooks.example.com/vestra
HTTP
# Stream a conversation live. If the connection drops, reconnect with the last seq you saw.curl -N "$VESTRA_BASE_URL/v1/conversations/conv_8f2k/events" \  -H "Authorization: Bearer $VESTRA_API_KEY" \  -H "Last-Event-ID: 41" # Read the same events as JSON. You get them in pages, after the seq you give.curl "$VESTRA_BASE_URL/v1/conversations/conv_8f2k/events?format=json&after=41" \  -H "Authorization: Bearer $VESTRA_API_KEY" # Read a task afterwards. You get every step of one task, with tokens and cost per turn.curl "$VESTRA_BASE_URL/v1/tasks/task_91d/trace" \  -H "Authorization: Bearer $VESTRA_API_KEY" # Send events to your server. Register a URL and the events it wants. The signing secret is shown only once.curl "$VESTRA_BASE_URL/v1/webhooks" \  -H "Authorization: Bearer $VESTRA_API_KEY" \  -H "Content-Type: application/json" \  -d '{ "url": "https://hooks.example.com/vestra", "events": ["task.completed", "interaction.created", "usage.cap_reached"] }' # Catch up on what you missed. List the events your webhooks were sent, newest first.curl "$VESTRA_BASE_URL/v1/events?type=task.failed" \  -H "Authorization: Bearer $VESTRA_API_KEY"
MCP
{  "method": "tools/call",  "params": {    "name": "events",    "arguments": { "user": "traveller-42", "conversation": "conv_8f2k", "after": 0 }  }}
GET/v1/webhooksYour endpoints.

Your API key, scope setup or all. On the card: events. Over HTTP it is made from the contract: fill in every value.

GET/v1/webhooks/{endpoint_id}One endpoint.

Your API key, scope setup or all. On the card: events. Over HTTP it is made from the contract: fill in each {…} and every value.

PATCH/v1/webhooks/{endpoint_id}Change URL or events, switch it on or off.

Your API key, scope setup or all. On the card: events. Over HTTP it is made from the contract: fill in each {…} and every value.

DELETE/v1/webhooks/{endpoint_id}Remove it.

Your API key, scope setup or all. On the card: events. Over HTTP it is made from the contract: fill in each {…} and every value.

POST/v1/webhooks/{endpoint_id}/roll-secretNew signing secret; the old one is accepted for 24 hours.

Your API key, scope setup or all. On the card: events. Over HTTP it is made from the contract: fill in each {…} and every value.

POST/v1/webhooks/{endpoint_id}/testSend a sample event now.

Your API key, scope setup or all. On the card: events. Every call here is a checked sample.

GET/v1/webhooks/{endpoint_id}/deliveriesEvery attempt with status code and timing.

Your API key, scope setup or all. On the card: events. Over HTTP it is made from the contract: fill in each {…} and every value.

POST/v1/webhooks/{endpoint_id}/deliveries/{delivery_id}/retrySend one again.

Your API key, scope setup or all. On the card: events. Over HTTP it is made from the contract: fill in each {…} and every value.

GET/v1/eventsThe same events as a list you can pull, for anything you missed.

Your API key, scope runtime or all. On the card: events. Every call here is a checked sample.

GET/v1/events/{event_id}One event.

Your API key, scope runtime or all. On the card: events. Over HTTP it is made from the contract: fill in each {…} and every value.