# Webhooks

Source: https://docs.simail.ai/api/webhooks/

> Read webhook endpoints, their header names and delivery logs. Creating, changing and deleting webhooks is human-only.

Webhook endpoints are managed by humans in the console. Keys can read them. How deliveries are signed,
retried and disabled: [Webhooks guide](/webhooks/).

```json
{
  "webhook_id": "whk_01JZX4E0F1G2H3J4K5M6N7P8Q9",
  "url": "https://example.com/simail-webhook",
  "event_types": ["message.received", "thread.locked", "thread.unlocked"],
  "pod_ids": [],
  "inbox_ids": ["shop-helper@simail.email"],
  "include_non_wake": false,
  "status": "enabled",
  "disabled_reason": null,
  "client_id": null,
  "created_at": "2026-10-18T16:50:00Z",
  "updated_at": "2026-10-18T16:50:00Z"
}
```

`status` is `enabled`, `disabled` (by a human) or `auto_disabled` (`disabled_reason`: `gone` after a
`410`, or `failing_5d`). The signing secret is never returned.

## List and get

`GET /v0/webhooks`

`GET /v0/webhooks/{webhook_id}`

Permission `webhook_read`. The list is paginated (`webhooks`).

## Custom header names

`GET /v0/webhooks/{webhook_id}/headers`

Permission `webhook_read`. Returns the **names** of custom headers only (`{ "headers": ["x-team"] }`);
values are stored encrypted and never returned.

## Delivery log

`GET /v0/webhooks/{webhook_id}/deliveries`

Permission `webhook_read`. One row per attempt, newest first, kept 30 days:

```json
{
  "count": 1,
  "limit": 50,
  "deliveries": [
    { "event_id": "evt_01JZX4F0G1H2J3K4M5N6P7Q8R9", "event_type": "message.received", "attempt": 1, "status": "delivered", "status_code": 200, "duration_ms": 182, "error": null, "created_at": "2026-10-18T17:02:13Z" }
  ]
}
```

`status` is `delivered`, `failed` (will retry), `dead` (retries exhausted), or `replayed`. Response
bodies are never stored.

## Human only

`POST /v0/webhooks` · `PATCH /v0/webhooks/{webhook_id}` · `DELETE /v0/webhooks/{webhook_id}` ·
`PATCH /v0/webhooks/{webhook_id}/headers`

All return `403 human_required`. Testing, replaying and rotating secrets are console actions too.
This is deliberate: a key that could add an endpoint could forward all your mail events elsewhere.

## Inbox and pod variants

`/v0/inboxes/{inbox_id}/webhooks…` and `/v0/pods/{pod_id}/webhooks…` behave the same, limited to
endpoints filtered to that inbox or pod.

`/v0/webhooks/polling` returns `501 not_implemented`; use [`GET /v0/events`](/events/).
