Webhook endpoints
A webhook endpoint is a URL on your server where Proof sends events: a comment, a mention, a suggestion accepted, a document an agent created, a seal. You turn them into notifications, emails and updates in your own lists. You can manage endpoints here or in the console. See Send notifications for a worked example and Webhook events for every event and its payload.
Test and live mode have separate endpoints: events from test documents go only to endpoints created with a test key.
The webhook endpoint object
Section titled “The webhook endpoint object”| Attribute | Type | Description |
|---|---|---|
id |
string | The endpoint’s id, starting we_. |
url |
string | Where Proof posts events. |
events |
array | The event types it receives, or ["*"] for all of them, including types added later. |
created_at |
timestamp | When it was created. |
secret |
string | The signing secret, starting whsec_. Returned only when you create the endpoint or roll its secret. |
{ "id": "we_5Kd2Hs8N", "url": "https://acme.com/proof/events", "events": ["thread.created", "thread.replied", "mention.created", "seal.created"], "created_at": "2026-10-30T18:20:00Z"}Create a webhook endpoint
Section titled “Create a webhook endpoint”POST /v1/webhook-endpoints
| Parameter | Type | Description |
|---|---|---|
url |
string, required | An https URL. With a test key, any URL, such as http://localhost:3000/proof/events or a tunnel. |
events |
array, required | Event types, such as ["mention.created", "seal.created"], or ["*"] for all. |
curl https://api.proof.exalto.ai/v1/webhook-endpoints \ -H "Authorization: Bearer $PROOF_SECRET_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://acme.com/proof/events", "events": ["thread.created", "thread.replied", "mention.created", "seal.created"] }'const endpoint = await proof.webhookEndpoints.create({ url: "https://acme.com/proof/events", events: ["thread.created", "thread.replied", "mention.created", "seal.created"],});// Store endpoint.secret now: it isn't shown again.Returns the endpoint with its secret, with 201.
{ "id": "we_5Kd2Hs8N", "url": "https://acme.com/proof/events", "events": ["thread.created", "thread.replied", "mention.created", "seal.created"], "created_at": "2026-10-30T18:20:00Z", "secret": "whsec_R4n8Vq2Lk7Tz1Mx9Pw3Hc6Bs"}| Error | When |
|---|---|
400 invalid_parameter on url |
Not a URL, or, with a live key, not https. |
400 invalid_parameter on events |
An event type doesn’t exist. |
List webhook endpoints
Section titled “List webhook endpoints”GET /v1/webhook-endpoints
Your endpoints in the current mode, newest first. Secrets aren’t included.
| Parameter | Type | Description |
|---|---|---|
limit |
integer | 1 to 100. Default 50. |
after |
string | The next cursor from the previous page. |
curl https://api.proof.exalto.ai/v1/webhook-endpoints \ -H "Authorization: Bearer $PROOF_SECRET_KEY"const page = await proof.webhookEndpoints.list();{ "data": [ { "id": "we_5Kd2Hs8N", "url": "https://acme.com/proof/events", "events": ["thread.created", "thread.replied", "mention.created", "seal.created"], "created_at": "2026-10-30T18:20:00Z" } ], "next": null}Roll a signing secret
Section titled “Roll a signing secret”POST /v1/webhook-endpoints/{endpoint_id}/roll-secret
Issues a new signing secret. For the next 24 hours Proof signs each event with both the old and the new secret, so you can deploy the new one without dropping events. See Verifying signatures.
| Parameter | Type | Description |
|---|---|---|
endpoint_id |
string, path, required | The endpoint’s id. |
curl https://api.proof.exalto.ai/v1/webhook-endpoints/we_5Kd2Hs8N/roll-secret \ -X POST \ -H "Authorization: Bearer $PROOF_SECRET_KEY"const { secret } = await proof.webhookEndpoints.rollSecret("we_5Kd2Hs8N");Returns the endpoint with its new secret.
Delete a webhook endpoint
Section titled “Delete a webhook endpoint”DELETE /v1/webhook-endpoints/{endpoint_id}
Stops sending events to the endpoint. Events already on their way, including retries, are dropped.
| Parameter | Type | Description |
|---|---|---|
endpoint_id |
string, path, required | The endpoint’s id. |
curl https://api.proof.exalto.ai/v1/webhook-endpoints/we_5Kd2Hs8N \ -X DELETE \ -H "Authorization: Bearer $PROOF_SECRET_KEY"await proof.webhookEndpoints.delete("we_5Kd2Hs8N");{ "id": "we_5Kd2Hs8N", "deleted": true}Delivery
Section titled “Delivery”Each event is a POST with a JSON body and a Proof-Signature header. Check the signature before you trust the body: proof.webhooks.verify(rawBody, header, secret) does it in Node. Answer with any 2xx within 10 seconds; anything else, or no answer, is retried with backoff for 3 days. Events can arrive more than once or out of order, so skip ids you’ve already handled. The webhook events reference has the signature format and every event’s payload.