Webhook Management
Manage webhook endpoints, inspect deliveries, rotate signing secrets, replay failures.
This page covers the management side of webhooks: creating endpoints, listing them, rotating their signing secrets, inspecting delivery attempts, and replaying failures.
For the receive-side contract (event catalog, signature verification, retry curve), see Webhooks.
| Scope | Endpoints |
|---|---|
webhooks:read | GET /webhooks, GET /webhooks/{id}, GET /webhooks/deliveries, GET /webhooks/deliveries/metrics, GET /webhooks/{id}/deliveries |
webhooks:write | POST /webhooks, PUT /webhooks/{id}, DELETE /webhooks/{id}, POST /webhooks/{id}/rotate-secret, POST /webhooks/{id}/test, POST /webhooks/deliveries/{id}/retry |
Base path: /api/v1/public/webhooks
Endpoint object
| Field | Type | Notes |
|---|---|---|
id | UUID | |
url | string | HTTPS URL. |
events | string[] | Event types the endpoint is subscribed to. |
description | string | null | Free-form, ≤ 500 chars. |
is_active | boolean | false if auto-disabled after 20 consecutive failures. |
last_success_at | ISO-8601 | null | |
last_failure_at | ISO-8601 | null | |
consecutive_failures | integer | Resets to 0 on the next successful delivery. |
created_at | ISO-8601 | |
updated_at | ISO-8601 | null |
POST /webhooks — Create an endpoint
curl -X POST https://api.lynkist.io/api/v1/public/webhooks \
-H "Authorization: Bearer $LYNKIST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/lynkist/webhook",
"events": ["message.sent", "message.delivered", "message.failed"],
"description": "Primary message-status sink",
"active": true
}'| Field | Required | Notes |
|---|---|---|
url | Yes | Must be HTTPS. |
events | Yes | Non-empty. Each must be a known event from the event catalog. |
description | No | ≤ 500 chars. |
active | No (true) | Disable on create if you want to register the secret before going live. |
201 Created
{
"data": {
"id": "wh-…",
"url": "https://example.com/lynkist/webhook",
"events": ["message.sent", "message.delivered", "message.failed"],
"description": "Primary message-status sink",
"is_active": true,
"last_success_at": null,
"last_failure_at": null,
"consecutive_failures": 0,
"created_at": "2026-05-31T08:00:00Z",
"updated_at": null
},
"signing_secret": "whsec_a1b2c3d4…"
}signing_secret is shown once. Store it securely; you cannot retrieve it again. If you
lose it, rotate it.
GET /webhooks — List endpoints
curl https://api.lynkist.io/api/v1/public/webhooks \
-H "Authorization: Bearer $LYNKIST_API_KEY"200 OK — { "data": [endpoint, …] }. Not paginated.
GET /webhooks/{id} — Get an endpoint
curl https://api.lynkist.io/api/v1/public/webhooks/wh-… \
-H "Authorization: Bearer $LYNKIST_API_KEY"200 OK — the endpoint object.
PUT /webhooks/{id} — Update an endpoint
All fields are optional — send only what changes.
curl -X PUT https://api.lynkist.io/api/v1/public/webhooks/wh-… \
-H "Authorization: Bearer $LYNKIST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"events": ["message.sent", "message.delivered", "message.read", "message.failed"],
"active": true
}'Setting active: true is how you re-enable an endpoint that was auto-disabled.
200 OK — the updated endpoint object.
DELETE /webhooks/{id} — Delete an endpoint
curl -X DELETE https://api.lynkist.io/api/v1/public/webhooks/wh-… \
-H "Authorization: Bearer $LYNKIST_API_KEY"200 OK — { "message": "Webhook endpoint deleted" }. Delivery history for the endpoint is
retained for audit, but no further events will be queued.
POST /webhooks/{id}/rotate-secret — Rotate signing secret
Generates a new secret and returns it once. The previous secret stops authenticating immediately — there is no grace period, so plan to update your receiver before calling this in production.
curl -X POST https://api.lynkist.io/api/v1/public/webhooks/wh-…/rotate-secret \
-H "Authorization: Bearer $LYNKIST_API_KEY"200 OK
{
"message": "Signing secret rotated",
"signing_secret": "whsec_x9y8z7w6…"
}POST /webhooks/{id}/test — Send a test event
Queues a webhook.test event for this endpoint. The body is a deterministic envelope you can
use to validate signature verification end-to-end without waiting for real traffic. The
delivery also adds the header X-Lynkist-Verification: true so receivers can route test
traffic separately.
curl -X POST https://api.lynkist.io/api/v1/public/webhooks/wh-…/test \
-H "Authorization: Bearer $LYNKIST_API_KEY"200 OK
{
"message": "Test webhook queued",
"delivery_id": "del-…"
}Use GET /webhooks/{id}/deliveries (or GET /webhooks/deliveries) to inspect the delivery
result and the response status your endpoint returned.
Delivery inspection
GET /webhooks/{id}/deliveries — Per-endpoint deliveries
curl "https://api.lynkist.io/api/v1/public/webhooks/wh-…/deliveries?status=failed&page=1&limit=20" \
-H "Authorization: Bearer $LYNKIST_API_KEY"| Query | Notes |
|---|---|
status | One of pending, success, failed, retrying, abandoned. |
page | ≥ 1 (default 1). |
limit | 1-100 (default 20). |
200 OK
{
"data": [
{
"id": "del-…",
"webhook_endpoint_id": "wh-…",
"event_id": "evt_…",
"event_type": "message.delivered",
"request_url": "https://example.com/lynkist/webhook",
"status": "success",
"attempt_number": 1,
"response_status_code": 200,
"response_time_ms": 142,
"error_message": null,
"next_retry_at": null,
"created_at": "2026-05-31T08:00:00Z",
"completed_at": "2026-05-31T08:00:00Z"
}
],
"pagination": { /* … */ }
}GET /webhooks/deliveries — All deliveries (cross-endpoint)
Same filters and shape as the per-endpoint version, but spans every endpoint the tenant owns.
GET /webhooks/deliveries/metrics — Delivery metrics
curl https://api.lynkist.io/api/v1/public/webhooks/deliveries/metrics \
-H "Authorization: Bearer $LYNKIST_API_KEY"200 OK
{
"total": 12_443,
"success": 12_201,
"retrying": 14,
"abandoned": 86,
"pending": 142,
"success_rate": 0.9805
}Retrying a failed delivery
POST /webhooks/deliveries/{id}/retry — Replay a delivery
Replays the original payload to the endpoint. The replay creates a new delivery row —
look at the returned delivery_id for the new attempt; the original is untouched.
curl -X POST https://api.lynkist.io/api/v1/public/webhooks/deliveries/del-…/retry \
-H "Authorization: Bearer $LYNKIST_API_KEY"200 OK
{
"message": "Delivery retry queued",
"delivery_id": "del-new-…"
}Use this for an abandoned delivery you want to attempt again after fixing your receiver, or
for debugging signature verification on an arbitrary historical event.
Errors
| Status | When |
|---|---|
400 | Body malformed; URL not HTTPS |
401 | Missing / invalid API key |
403 | Key lacks webhooks:read or webhooks:write |
404 | Endpoint or delivery not found |
422 | Unknown event type in events (Pydantic validator surfaces every valid option) |
Notes
- Route ordering.
/webhooks/deliveries/*literals are matched before/{webhook_id}, so the order you write requests in your client does not matter —deliveriesis never confused with a UUID. - Endpoint URLs must be HTTPS. Lynkist rejects
http://URLs at the schema level. webhook.testenvelopes carry the same signature as any other event — use them to validate signature verification on first integration.