Webhooks
See the Webhooks guide for events, signatures and retries. Operator and above.
| Endpoint | What it does |
|---|---|
GET /webhook-endpoints | The account’s webhooks, and eventTypes, the events you can subscribe to. |
POST /webhook-endpoints | Add one. Send a client-generated id (whk_…), an https url, events (a list, or ["*"]) and a sealed meta naming it. Returns webhook and its secret, shown only this once. 10 per account. Session only. |
PATCH /webhook-endpoints/:id | Change url, events or meta, or set status to active or disabled. Switching one back on clears its failure record. Session only. |
DELETE /webhook-endpoints/:id | Remove it and its delivery log. Session only. |
POST /webhook-endpoints/:id/rotate-secret | A new secret, shown only this once. The old one stops working at once. Session only. |
POST /webhook-endpoints/:id/test | Send a webhook.test event. Returns the deliveryId and eventId. Tests and redeliveries together are limited to 60 an hour. |
GET /webhook-endpoints/:id/deliveries | The delivery log, newest first, 50 at a time or limit up to 200. Filter with status (pending, succeeded or failed) and page with cursor. Returns deliveries and nextCursor. Kept 30 days. |
POST /webhook-endpoints/:id/deliveries/:deliveryId/redeliver | Send that delivery’s event again, with the same event id. Returns the new deliveryId. |
“Session only” endpoints answer 403 session_required to an API key. An API key can list webhooks, read the delivery log, send a test and redeliver.
A webhook returns:
{ "id": "whk_k3v9x2mq7a8b", "url": "https://example.com/mailcycle", "events": ["message.received"], "meta": { "…": "sealed" }, "status": "active", "disabledReason": null, "failingSince": null, "lastSuccessAt": "2026-09-19T09:14:04.000Z", "createdAt": "2026-09-18T10:02:11.000Z"}failingSince is set while every attempt since the last success has failed. disabledReason says why a webhook is off.
A delivery returns id, eventId, eventType, the event exactly as sent, status, attempts, responseStatus, error, createdAt, lastAttemptAt and nextAttemptAt.
Errors
Section titled “Errors”| Code | Status | Meaning |
|---|---|---|
invalid_url | 400 | The URL is not https, uses an IP address or a local name, or points at Mailcycle. |
plan_required | 403 | The plan does not include webhooks. |
limit_reached | 409 | The account already has 10 webhooks. |
webhook_disabled | 409 | Switch the webhook on before sending a test or an event again. |
feature_disabled | 503 | Adding webhooks is paused for everyone. Deliveries to existing webhooks wait and go out afterwards. |
© Northlab Studios Ltd, trading as Mailcycle. Registered in England and Wales, company no. 17462734. Registered office: 167-169 Great Portland Street, London W1W 5PF.