### Read the delivery log

`GET /api/v1/admin/webhooks/deliveries`

One page of delivery attempts, newest first, without the payload bodies. This is where you diagnose an integration that is not receiving events.

- Authentication: manager session (JWT) or API token
- Permission: `prm_notifications_manage` (Manage notification channels & templates)
- Risk: write

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `filter[endpoint_id]` | query | integer | no | Narrow to one endpoint. Also accepted as a bare endpoint_id parameter. |
| `filter[state]` | query | enum | no | queued, sending, sent, failed or dead. An unknown value is a 400. |
| `sort` | query | string | no | queued_at, state, attempts or id. Defaults to queued_at descending. |

#### Response — 200 OK

```json
{
  "data": [
    {
      "id": 77120,
      "endpoint_id": 4,
      "event_type": "user.created",
      "state": "failed",
      "attempts": 3,
      "max_attempts": 6,
      "response_code": 502,
      "response_ms": 1204,
      "last_error": "upstream returned 502",
      "url": "https://hooks.acme.example/xradius",
      "queued_at": "2026-09-20 09:00:00",
      "sent_at": "2026-09-20 09:04:11",
      "next_attempt_at": "2026-09-20 09:20:00"
    }
  ],
  "meta": { "page": 1, "page_size": 50, "total": 4102, "has_next": true }
}
```

#### Errors

| Code | Status | When |
| --- | --- | --- |
| `ERR_VALIDATION` | 400 | an unknown state filter, or a non-numeric endpoint_id |

#### Note

failed and dead are different. failed means it will be retried, and next_attempt_at says when; dead means the attempt budget is spent and nothing further will happen without a replay. An integration that went quiet has rows in dead, not failed.

