# Export sent messages as CSV

`POST /v1/messages/exports`

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

Queues a CSV of the send log. The body takes the filters of `GET /v1/messages/deliveries` (`status`, `channel`, `recipient`, `messageType`, `createdAfter`, `createdBefore`) and applies them the same way; send `{}` for every message. A filter matching no message is refused with `NOTHING_TO_EXPORT`. The file is generated in the background: poll the export until `status` is `ready`, then download it. Any key of the workspace with `messages:read` can read the export.

## Request body

- `status` (string, optional, one of `queued`, `sending`, `skipped`, `sent`, `failed`, `delivered`, `bounced`, `complained`) — Only messages in this status.
- `channel` (string, optional, one of `email`, `push`) — Only messages on this channel.
- `recipient` (string, optional) — The exact address the message went to.
- `q` (string, optional, 1–100 characters) — Part of the recipient's email address or name, matched against the contact the message went to.
- `messageType` (string, optional, one of `marketing`, `transactional`) — Only messages of this type, such as campaign or transactional.
- `createdAfter` (string, optional, date-time) — Only messages accepted at or after this time (inclusive).
- `createdBefore` (string, optional, date-time) — Only messages accepted before this time (exclusive).

## Returns

Returns `202 Accepted` with a `MessageExport` in `data`. Otherwise returns an error; [Errors](/docs/api/errors) lists every code and which to retry.

- `id` (string, required, uuid)
- `status` (string, required, one of `queued`, `generating`, `ready`, `failed`, `expired`) — `queued`, `generating`, then `ready` or `failed`; `expired` once the file is deleted.
- `rowCount` (integer | null, required, min -9007199254740991, max 9007199254740991) — Rows in the file, once it is ready.
- `filters` (MessageExportFilters, required) — The filters the export was created with.
  - `status` (string, optional, one of `queued`, `sending`, `skipped`, `sent`, `failed`, `delivered`, `bounced`, `complained`) — Only messages in this status.
  - `channel` (string, optional, one of `email`, `push`) — Only messages on this channel.
  - `recipient` (string, optional, email, up to 320 characters) — The exact address the message went to.
  - `q` (string, optional, 1–100 characters) — Part of the recipient's email address or name, matched against the contact the message went to.
  - `messageType` (string, optional, one of `marketing`, `transactional`) — Only messages of this type, such as campaign or transactional.
  - `createdAfter` (string, optional, date-time) — Only messages accepted at or after this time (inclusive).
  - `createdBefore` (string, optional, date-time) — Only messages accepted before this time (exclusive).
- `createdAt` (string, required, date-time)
- `completedAt` (string | null, required, date-time)
- `expiresAt` (string | null, required, date-time) — When the file is deleted; the export then reads `expired`.
- `failureCode` (string | null, required) — `EXPORT_TOO_LARGE` or `GENERATION_FAILED` when `status` is `failed`.

## Example

```bash
curl -X POST https://api.kirora.io/v1/messages/exports \
  -H "Authorization: Bearer $KIRORA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "queued",
    "channel": "email",
    "recipient": "recipient_example",
    "q": "q_example",
    "messageType": "marketing",
    "createdAfter": "2030-03-14T09:30:00Z",
    "createdBefore": "2030-03-14T09:30:00Z"
  }'
```

Response `202`:

```json
{
  "data": {
    "id": "018f2a4e-6b1c-7d3e-9f40-37386ae05a6b",
    "status": "queued",
    "rowCount": -9007199254740991,
    "filters": {},
    "createdAt": "2030-03-14T09:30:00Z",
    "completedAt": "2030-03-14T09:30:00Z",
    "expiresAt": "2030-03-14T09:30:00Z",
    "failureCode": "failureCode_example"
  }
}
```
