# List Notifications

> The key creator's notifications in this workspace, newest first.

Requires an API key with the `read` scope.

Returns the notifications of the user who created the key, in the key's workspace. Notifications are kept for 90 days. Pagination is by page, with `meta.hasMore` telling you whether another page exists.

## Query Parameters

<ParamField query="page" type="integer">Page number, starting at 1. Default 1.</ParamField>
<ParamField query="pageSize" type="integer">Rows per page, 1 to 100. Default 20.</ParamField>
<ParamField query="unread" type="boolean">Only notifications that are not read yet. Default false.</ParamField>
<ParamField query="category" type="string">Comma-separated filter: `replies`, `campaigns`, `inboxes`, `imports`, `billing`, `workspace`. Several values match any of them. Leave it out for every category.</ParamField>

## Response

<ResponseField name="data" type="array">
  <Expandable title="Notification">
    <ResponseField name="id" type="string">Notification identifier.</ResponseField>
    <ResponseField name="type" type="string">What happened, for example `campaign_completed`, `campaign_autopaused`, `account_disconnected`, `import_completed`, `interested_replies`, `payment_failed`.</ResponseField>
    <ResponseField name="title" type="string">One line summary.</ResponseField>
    <ResponseField name="body" type="string">Detail line, or `null`.</ResponseField>
    <ResponseField name="href" type="string">App path the notification points to, for example `/campaigns/abc`, or `null`.</ResponseField>
    <ResponseField name="category" type="string">The pill the notification belongs to: `replies`, `campaigns`, `inboxes`, `imports`, `billing` or `workspace`.</ResponseField>
    <ResponseField name="meta" type="object">Identifiers and counts for the event, or `null`.</ResponseField>
    <ResponseField name="details" type="array">What the row shows when it is expanded, at most 10 items of `label`, `value`, `text`, `href` and `at` (each optional except `label`). For interested replies one item per reply: the lead, the first line of the reply, the time and the inbox thread. Empty when there is nothing more to show.</ResponseField>
    <ResponseField name="detailsMore" type="integer">How many items exist beyond the ones in `details`.</ResponseField>
    <ResponseField name="count" type="integer">How many events the row stands for. Interested replies to one campaign collapse into one row until you read it.</ResponseField>
    <ResponseField name="read" type="boolean">Whether it has been read.</ResponseField>
    <ResponseField name="readAt" type="string">ISO 8601 time it was read, or `null`.</ResponseField>
    <ResponseField name="createdAt" type="string">ISO 8601 time of the event (the latest one for a grouped row).</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="meta" type="object">`page`, `pageSize`, `hasMore` and `enabled`.</ResponseField>

<RequestExample>
```bash cURL
curl "https://api.foxreach.io/api/v1/notifications?unread=true&pageSize=20" \
  -H "X-API-Key: otr_your_key"
```

```python Python SDK (beta)
from foxreach import FoxReach

client = FoxReach(api_key="otr_your_key")
page = client.notifications.list(unread=True, page_size=20, category="replies,billing")
```

```typescript TypeScript SDK (beta)
import { FoxReach } from "foxreach";

const client = new FoxReach({ apiKey: "otr_your_key" });
const page = await client.notifications.list({ unread: true, pageSize: 20, category: ["replies", "billing"] });
```

</RequestExample>

<ResponseExample>
```json
{
  "data": [
    {
      "id": "clx1abc",
      "type": "interested_replies",
      "title": "3 interested replies in Q4 outbound",
      "body": null,
      "href": "/inbox?category=interested",
      "category": "replies",
      "meta": { "campaignId": "clx0camp" },
      "details": [
        { "label": "Dana Lee", "text": "Yes, send me the pricing.", "href": "/inbox?thread=clx9rep", "at": "2026-11-04T09:12:44+00:00" }
      ],
      "detailsMore": 2,
      "count": 3,
      "read": false,
      "readAt": null,
      "createdAt": "2026-11-04T09:12:44+00:00"
    }
  ],
  "meta": { "page": 1, "pageSize": 20, "hasMore": false, "enabled": true }
}
```
</ResponseExample>

## Errors

| Status | Description |
|--------|-------------|
| `401` | Missing, invalid, revoked or expired API key |
| `403` | API key does not have the required scope: `read` |
| `422` | `page` or `pageSize` out of range, or `category` has a value that is not one of the six |

## Rate Limit

- **300 requests per minute, shared by every `read` call in your workspace.** Fixed 60-second window.
- Every response includes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` (unix epoch seconds) and `X-RateLimit-Bucket` (`read`).
- A `429` response includes a `Retry-After` header (seconds until the bucket resets).

For client-side patterns, see [Rate Limiting](/rate-limiting).
