# List activities for a client

**GET** `/clients/{clientId}/activities`

Returns the client's activities (emails, meetings, notes, chats)
ordered by most-recent first.

**Pagination.** Offset-based: `cursor` is the integer offset of the
next page encoded as a decimal string (e.g. `"20"`). This differs from
`/clients`, whose cursor is a base64-encoded UUID — the two endpoints
paginate differently and their cursors are not interchangeable.

**Filters.** `type`, `source`, `from`, `to`, and `includeArchived` are
all applied server-side. `from`/`to` bound the activity's `occurredAt`
(inclusive) and accept an ISO-8601 date (`2026-01-01`) or an RFC 3339
datetime. Archived activities are hidden unless `includeArchived=true`.
Unknown enum values, unparseable dates, or a non-boolean
`includeArchived` return `400 invalid_argument`.

List responses omit `content` for cost reasons — fetch the
single-resource endpoint to get message bodies.

Base URL: `https://api.salfio.com/v1`

Tags: `activities`

## Authorization

| Option | Scheme | Type | Sent as | Scopes |
| --- | --- | --- | --- | --- |
| Option 1 | `bearerAuth` | `http` | `Authorization: Bearer <token>` | — |

## Path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `clientId` | `string` (uuid) | Yes | Client UUID. |

## Query parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `limit` | `integer` | No | — |
| `cursor` | `string` | No | Decimal-string offset of the next page (from a prior response's `meta.cursor`). |
| `type` | `string` | No | Allowed values: `email`, `meeting`, `note`, `chat`. |
| `source` | `string` | No | Allowed values: `manual`, `gmail`, `outlook`, `fireflies`. |
| `from` | `string` | No | Only activities whose `occurredAt` is on/after this instant. ISO-8601 date or RFC 3339 datetime. |
| `to` | `string` | No | Only activities whose `occurredAt` is on/before this instant. ISO-8601 date or RFC 3339 datetime. |
| `includeArchived` | `boolean` | No | When true, archived activities are included. Defaults to false. |

## Responses

| Status | Description | Media type |
| --- | --- | --- |
| `200` | Page of activities. | `application/json` |
| `400` | Request body / query parameters failed validation. | `application/json` |
| `401` | Missing or invalid bearer token. The message is intentionally opaque — do not rely on it to distinguish "missing" from "invalid". | `application/json` |
| `404` | The referenced resource does not exist, or belongs to a different organization than the one owning the API key. The public API does not distinguish between these cases — both return 404 to avoid leaking cross-tenant existence. | `application/json` |
| `429` | Per-organization or per-endpoint rate limit exceeded. | `application/json` |

### Example response: 200 — Page of activities.

```json
{
  "data": [
    {
      "archivedAt": "2026-06-09T00:00:00Z",
      "clientId": "00000000-0000-0000-0000-000000000000",
      "content": "string",
      "createdAt": "2026-06-09T00:00:00Z",
      "id": "00000000-0000-0000-0000-000000000000",
      "immutable": true,
      "occurredAt": "2026-06-09T00:00:00Z",
      "participants": [
        "user@example.com"
      ],
      "source": "fireflies",
      "subject": "string",
      "type": "chat",
      "updatedAt": "2026-06-09T00:00:00Z"
    }
  ],
  "meta": {
    "cursor": "string",
    "hasMore": true
  }
}
```

### Example response: 400 — Request body / query parameters failed validation.

```json
{
  "error": {
    "code": "invalid_argument",
    "message": "limit must be an integer between 1 and 100"
  }
}
```

### Example response: 401 — Missing or invalid bearer token. The message is intentionally opaque — do not rely on it to distinguish "missing" from "invalid".

```json
{
  "error": {
    "code": "unauthorized",
    "message": "Authentication required"
  }
}
```

### Example response: 404 — The referenced resource does not exist, or belongs to a different
organization than the one owning the API key. The public API does not
distinguish between these cases — both return 404 to avoid leaking
cross-tenant existence.

```json
{
  "error": {
    "code": "not_found",
    "message": "client not found"
  }
}
```

### Example response: 429 — Per-organization or per-endpoint rate limit exceeded.

```json
{
  "error": {
    "code": "rate_limited",
    "details": {
      "retry_after_seconds": 30
    },
    "message": "Rate limit exceeded"
  }
}
```

## Related pages

- [activities](./tags/activities.md)
- [assignment-rules](./tags/assignment-rules.md)
- [Authenticated health check](./gethealth.md)
- [cards](./tags/cards.md)
- [clients](./tags/clients.md)
- [Create a client](./createclient.md)
- [Create a manual activity](./createactivity.md)
- [Create a note on a client](./createnote.md)
- [Delete a client](./deleteclient.md)
- [Delete or archive an activity](./deleteorarchiveactivity.md)

# Agent Instructions

This portal answers questions programmatically. To receive a synthesized,
source-cited answer instead of crawling page by page, append the `?ask=`
query parameter to any page URL on this site:

    /guides/quickstart?ask=how+do+I+authenticate

Optional parameters:

- `&goal=<what-you-are-trying-to-do>` steers the answer toward your
  objective (e.g. `&goal=write+a+python+client`).
- `&version=<label>` scopes the answer to a mounted version when the
  portal publishes more than one.

The response is `text/markdown`: the answer followed by a `# Sources` list
of the portal pages it was grounded in. Status codes are the contract:

- `200` — the answer; `402` — the portal owner’s plan or answer credits are
  exhausted (surface this to your operator; do NOT retry); `429` — you are
  rate-limited; back off for the `Retry-After` seconds; `503` — the answer
  lane is temporarily unavailable; fall back to crawling the `.md` pages.

For the full corpus map read `llms.txt` at the site root; for the tool
surface (search + page fetch as MCP tools) see `/mcp`.
