Webhook Endpoints
Register, manage, and debug the HTTPS endpoints that receive Stile's signed event notifications.
A webhook endpoint is an HTTPS URL on your server where Stile delivers signed events — session verified, failed, expired, and more. This page covers the management API: creating endpoints, rotating secrets, and inspecting individual deliveries. For signature verification and handler patterns, see the Webhooks guide. You can also manage endpoints in the dashboard.
Examples show cURL, Python, Go, and Node.js. You can also use the Node.js SDK as a typed convenience wrapper.
Live orgs require a webhook endpoint
You cannot create verification sessions until at least one active webhook endpoint exists (the API
returns 400 webhook_required). Sandbox organizations are exempt.
The webhook endpoint object
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier, prefixed we_. |
url | string | The HTTPS URL events are delivered to. |
enabled_events | string[] | Subscribed event types. ["*"] means all events. |
status | string | enabled or disabled. Disabled endpoints receive no deliveries. |
description | string | Human-readable label. |
metadata | object | Key-value string pairs you attach. |
secret | string | The signing secret used to compute Stile-Signature. Returned once — on create and on rotate only. |
Create an endpoint
/v1/webhook_endpointsYour endpoint must be a publicly reachable HTTPS URL (plain HTTP is allowed for sandbox/local testing only) and must respond with a 2xx within 30 seconds. Return a 2xx as soon as you've queued the work — process asynchronously.
| Parameter | Type | Description |
|---|---|---|
urlrequired | string | The HTTPS URL to deliver events to. |
enabled_eventsrequired | string[] | Event types to subscribe to. Use ["*"] to receive all events. |
description | string | A human-readable label for this endpoint. |
metadata | object | Key-value string pairs to attach to the endpoint. |
curl https://api.stile.id/v1/webhook_endpoints \
-H "Authorization: Bearer stile_sk_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourapp.com/api/webhooks",
"enabled_events": ["verification_session.verified", "verification_session.failed"]
}'import requests
res = requests.post(
"https://api.stile.id/v1/webhook_endpoints",
headers={"Authorization": "Bearer stile_sk_..."},
json={
"url": "https://yourapp.com/api/webhooks",
"enabled_events": [
"verification_session.verified",
"verification_session.failed",
],
"description": "Production webhook",
},
)
endpoint = res.json()
# IMPORTANT: save endpoint["secret"] — it's only shown once!
print("Webhook secret:", endpoint["secret"])body := strings.NewReader(`{
"url": "https://yourapp.com/api/webhooks",
"enabled_events": ["verification_session.verified", "verification_session.failed"],
"description": "Production webhook"
}`)
req, _ := http.NewRequest("POST", "https://api.stile.id/v1/webhook_endpoints", body)
req.Header.Set("Authorization", "Bearer stile_sk_...")
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)const endpoint = await stile.webhookEndpoints.create({
url: "https://yourapp.com/api/webhooks",
enabled_events: [
"verification_session.verified",
"verification_session.failed",
"verification_session.expired",
],
description: "Production webhook",
});
// IMPORTANT: save endpoint.secret — it's only shown once!
console.log("Webhook secret:", endpoint.secret);Store the secret immediately
The response includes the endpoint's signing secret exactly once. Store it in your secret
manager right away — you need it to verify the Stile-Signature header on every delivery. If you
lose it, rotate the secret to get a new one.
Retrieve an endpoint
/v1/webhook_endpoints/:idconst endpoint = await stile.webhookEndpoints.retrieve("we_abc123");The secret is not included — it is only returned on create and rotate.
Update an endpoint
/v1/webhook_endpoints/:id| Parameter | Type | Description |
|---|---|---|
url | string | New delivery URL. |
enabled_events | string[] | Replace the subscribed event types. |
status | "enabled" | "disabled" | Pause or resume delivery without deleting the endpoint. |
description | string | Update the label. |
metadata | object | Replace all metadata key-value pairs. |
// Subscribe to all events
await stile.webhookEndpoints.update("we_abc123", {
enabled_events: ["*"],
});
// Temporarily pause delivery
await stile.webhookEndpoints.update("we_abc123", {
status: "disabled",
});Delete an endpoint
/v1/webhook_endpoints/:idawait stile.webhookEndpoints.del("we_abc123");List endpoints
/v1/webhook_endpointscurl https://api.stile.id/v1/webhook_endpoints \
-H "Authorization: Bearer stile_sk_..."import requests
res = requests.get(
"https://api.stile.id/v1/webhook_endpoints",
headers={"Authorization": "Bearer stile_sk_..."},
)
data = res.json()req, _ := http.NewRequest("GET", "https://api.stile.id/v1/webhook_endpoints", nil)
req.Header.Set("Authorization", "Bearer stile_sk_...")
res, _ := http.DefaultClient.Do(req)const { data } = await stile.webhookEndpoints.list();Rotate the signing secret
/v1/webhook_endpoints/:id/rotate-secretGenerates a new signing secret for the endpoint and returns it once.
curl -X POST https://api.stile.id/v1/webhook_endpoints/we_abc123/rotate-secret \
-H "Authorization: Bearer stile_sk_..."Rotation takes effect immediately
Update your environment variables as soon as you rotate — deliveries signed with the old secret will stop validating.
List deliveries
/v1/webhook_endpoints/:id/deliveriesReturns a paginated list of delivery attempts for a specific endpoint, newest first. Useful for debugging failed deliveries and monitoring webhook health. Each delivery records the event type, the attempt number, and the HTTP status your endpoint returned; the delivery's id is also sent to your endpoint as the Stile-Webhook-Id header.
| Parameter | Type | Description |
|---|---|---|
limit | number= 20 | Number of deliveries to return. |
starting_after | string | Delivery ID cursor for pagination. |
const { data } = await stile.webhookEndpoints.listDeliveries("we_abc123", {
limit: 10,
});
for (const delivery of data) {
console.log(delivery.event_type, delivery.response_status, delivery.attempt);
}Retrieve a delivery
/v1/webhook_endpoints/:id/deliveries/:deliveryIdReturns the full detail for a single delivery attempt, including the request payload and the response your endpoint returned — useful when debugging a failing handler.
Retry a delivery
/v1/webhook_endpoints/:id/deliveries/:deliveryId/retryRe-queues a failed delivery immediately instead of waiting for the automatic retry schedule (5 min → 30 min → 2 h → 8 h after the initial failure, after which the delivery is marked permanently failed — see the Webhooks guide).
curl -X POST https://api.stile.id/v1/webhook_endpoints/we_abc123/deliveries/whd_xyz789/retry \
-H "Authorization: Bearer stile_sk_..."Retries reuse the original event id but get a new delivery id — deduplicate your handler on the event id.
Event types
See the full catalog in the Events API reference — verification session lifecycle (verification_session.*), manual review outcomes (session_review.*), and trust-reuse grants (trust_reuse_grant.*, trust_reuse_consent.*). Use ["*"] in enabled_events to subscribe to everything.
Next steps
Webhooks guide
Delivery lifecycle, retry schedule, and handler best practices.
Verify signatures
Validate the Stile-Signature header in your framework of choice.
Events API
The event object and the complete event-type catalog.
Node.js SDK
Typed webhook endpoint management and signature verification helpers.