Lynkist Developers

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.

ScopeEndpoints
webhooks:readGET /webhooks, GET /webhooks/{id}, GET /webhooks/deliveries, GET /webhooks/deliveries/metrics, GET /webhooks/{id}/deliveries
webhooks:writePOST /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

FieldTypeNotes
idUUID
urlstringHTTPS URL.
eventsstring[]Event types the endpoint is subscribed to.
descriptionstring | nullFree-form, ≤ 500 chars.
is_activebooleanfalse if auto-disabled after 20 consecutive failures.
last_success_atISO-8601 | null
last_failure_atISO-8601 | null
consecutive_failuresintegerResets to 0 on the next successful delivery.
created_atISO-8601
updated_atISO-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
  }'
FieldRequiredNotes
urlYesMust be HTTPS.
eventsYesNon-empty. Each must be a known event from the event catalog.
descriptionNo≤ 500 chars.
activeNo (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"
QueryNotes
statusOne of pending, success, failed, retrying, abandoned.
page≥ 1 (default 1).
limit1-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

StatusWhen
400Body malformed; URL not HTTPS
401Missing / invalid API key
403Key lacks webhooks:read or webhooks:write
404Endpoint or delivery not found
422Unknown 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 — deliveries is never confused with a UUID.
  • Endpoint URLs must be HTTPS. Lynkist rejects http:// URLs at the schema level.
  • webhook.test envelopes carry the same signature as any other event — use them to validate signature verification on first integration.
Webhook Management — Lynkist Developers | Lynkist