# List a push message's deliveries

Source: https://kirora.io/docs/api/reference/listMessageDeliveries

`GET /v1/messages/{id}/deliveries`

Requires an API key with the `messages:read` scope. [About keys and scopes](https://kirora.io/docs/api/reference/authentication)

Works with integration, agent and partner keys.

Lists what each device reported for one push message: any message whose `channel` is `push`, from a campaign, a journey or a transactional send. A push reaches every ready installation of the contact, so a message has one delivery per device. `accepted`: Apple, Google or the browser's push service took it, which is not proof the device showed it. `invalid`: the device is gone and its installation was retired. `rejected`: refused, often the app's key or a payload the provider would not take. `retryable`: will be tried again. `unknown`: the provider may have taken it, so it is not resent. `skipped`: not attempted, as when the app's key was refused for another device of the same app. `pending` and `started` are still in flight. Any other message returns 404 `NOT_FOUND`: a missing one says `Message not found`, and one on another channel names it in `details.channel` (an email's delivery events are on the message itself).

## Path parameters

- `id` (string, required, uuid) — The message's id.

## Query parameters

- `limit` (integer, optional, min > 0, max 100, default `20`) — How many items a page holds: 1 to 100, 20 by default.
- `cursor` (string, optional, 1–2,048 characters) — Where the page starts: the previous page's `meta.pagination.nextCursor`. Omit it for the first page, and send the same filters with it.

## Header parameters

- `Kirora-Workspace` (string, optional, pattern `^[A-Za-z0-9._:-]{1,128}$`) — Partner keys only: the child workspace to act in, by the external id the partner gave it. Without it, a partner key acts in its own workspace. Any other key that sends it is refused with 403, and an unknown workspace is 404.

## Returns

Returns `200 OK` with a list of `PushDelivery` objects in `data`, and the next page's cursor in `meta` (see [pagination](https://kirora.io/docs/api/reference/pagination)). Otherwise returns an error; [Errors](https://kirora.io/docs/api/reference/errors) lists every code and which to retry.

- `id` (string, required, uuid)
- `installationId` (string, required, uuid) — The device the delivery went to.
- `platform` (string, required, one of `ios`, `android`, `web`)
- `status` (string, required, one of `pending`, `started`, `accepted`, `invalid`, `rejected`, `retryable`, `unknown`, `skipped`)
- `attemptCount` (integer, required, min 0) — Times sending was tried.
- `startedAt` (string | null, required, date-time) — When the first attempt began.
- `resolvedAt` (string | null, required, date-time) — When it reached a final status.
- `createdAt` (string, required, date-time)

## Example

```bash
curl https://api.kirora.io/v1/messages/018f2a4e-6b1c-7d3e-9f40-37386ae05a6b/deliveries \
  -H "Authorization: Bearer $KIRORA_API_KEY"
```

Response `200`:

```json
{
  "data": [
    {
      "id": "0192f3b1-5e6f-7071-8c83-9e0f1a2b3c4d",
      "installationId": "0192f3a2-6f70-7182-9d94-0f1a2b3c4d5e",
      "platform": "ios",
      "status": "accepted",
      "attemptCount": 1,
      "startedAt": "2026-10-01T09:30:01.000Z",
      "resolvedAt": "2026-10-01T09:30:02.000Z",
      "createdAt": "2026-10-01T09:30:00.000Z"
    },
    {
      "id": "0192f3b1-6f70-7182-9d94-0f1a2b3c4d5e",
      "installationId": "0192f3a2-7081-7293-8ea5-1a2b3c4d5e6f",
      "platform": "android",
      "status": "invalid",
      "attemptCount": 1,
      "startedAt": "2026-10-01T09:30:01.000Z",
      "resolvedAt": "2026-10-01T09:30:03.000Z",
      "createdAt": "2026-10-01T09:30:00.000Z"
    }
  ],
  "meta": {
    "pagination": {
      "limit": 20,
      "nextCursor": null
    }
  }
}
```
