# Activity

`GET /api/activity` returns the last 30 days of events in every workspace you belong to, newest first. Each event is a Change Sensei saw, such as a pull request merging, or an action a member took, such as starting a session. To get only what is new to you and mark it seen in the same call, pass `markSeen=true`.

| Method | Path                                                                              | Description                                                                                                                                                                                        |
| ------ | --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| GET    | `/api/activity?since=&unseen=&markSeen=&workspace=&project=&kind=&limit=&cursor=` | List Activity across every workspace you belong to, newest first: Changes the platform observed and what members did. Each event names its workspace. An agent token reads its own workspace only. |

In the web app the same events are under Settings > your workspace > Activity, one workspace at a time. See [Overview, Needs you and Activity](https://kosuke.ai/docs/sessions/home-and-activity.md).

## Query parameters

Every parameter is optional.

| Parameter | Values | Default |
| --- | --- | --- |
| `since` | An ISO date or time, or a span back from now in whole hours or days, such as `24h` or `7d`. | The last 30 days |
| `kind` | Kinds from the tables below, separated by commas. Or `change` alone for every Change, or `action` alone for every Member Action. | Every kind |
| `limit` | Events per page, from 1. Values above 200 are read as 200. | 50 |
| `cursor` | The `meta.pagination.nextCursor` of the previous page. | The first page |
| `workspace` | One workspace id. | Every workspace you belong to |
| `project` | One project id. | Every project |
| `unseen` | `true` returns only events that are New to you, oldest first. | `false` |
| `markSeen` | `true` returns your New events, oldest first, and marks them seen. See [Read only what is new](https://kosuke.ai/docs/endpoint-reference/activity.md#read-only-what-is-new). | `false` |

```bash
curl -s "https://app.kosuke.ai/api/activity?since=24h&kind=pr_merged,pr_checks_failed" \
  -H "Authorization: Bearer $KOSUKE_API_KEY"
```

```json
{
  "data": [
    {
      "id": "48213",
      "workspaceId": "YzH4k2P9sQ1mVx7bN3cR8tL5wD0fG6jA",
      "workspaceName": "Acme",
      "projectId": "3f6c1e0a-8b2d-4e57-9a41-0c2f7d9b5e18",
      "projectName": "storefront",
      "chatSessionId": "b1d6e2f4-7a3c-4c1e-9f0b-2e8d5a6c7b90",
      "sessionUrl": "https://app.kosuke.ai/projects/3f6c1e0a-8b2d-4e57-9a41-0c2f7d9b5e18/chat-sessions?session=b1d6e2f4-7a3c-4c1e-9f0b-2e8d5a6c7b90",
      "sessionPath": "/projects/3f6c1e0a-8b2d-4e57-9a41-0c2f7d9b5e18/chat-sessions?session=b1d6e2f4-7a3c-4c1e-9f0b-2e8d5a6c7b90",
      "actor": null,
      "kind": "pr_merged",
      "category": "change",
      "text": "#12 merged by Sam Rivera",
      "subject": "Fix the checkout total",
      "payload": {
        "sessionTitle": "Fix the checkout total",
        "pullRequestNumber": 12,
        "mergedBy": { "login": "sam-acme", "userId": "u8Rk2mQ4xT7vB1nP9sL3cW6yD0fH5jZa", "name": "Sam Rivera" }
      },
      "source": null,
      "createdAt": "2026-09-30T09:14:02.000Z",
      "isNew": true
    }
  ],
  "meta": {
    "pagination": { "pageSize": 50, "total": 1, "hasMore": false, "nextCursor": null },
    "workspaces": [{ "id": "YzH4k2P9sQ1mVx7bN3cR8tL5wD0fG6jA", "name": "Acme" }]
  }
}
```

| Field | Meaning |
| --- | --- |
| `text` | One line describing the event, ready to show a person. |
| `subject` | The session title or Cron name the event is about, or `null`. |
| `actor` | The member who acted, with `id`, `name` and `image`. `null` on a Change. |
| `category` | `change` or `action`. |
| `sessionUrl` | A link to the session in the web app. `null` once the session is deleted. The event itself stays. |
| `payload` | Details that depend on `kind`, such as a pull request number or a status change's `from` and `to`. |
| `source` | The agent that acted for `actor`, such as `{ "kind": "sensei" }`, shown as "via Sensei". `null` when the member acted by hand, and always `null` on a Change. |
| `isNew` | `true` when the event is New to you. |

`meta.workspaces` lists the workspaces the call read. When `hasMore` is `true`, pass `nextCursor` back as `cursor` for the next page.

In the CLI, run `kosuke activity list --since 24h --kind pr_merged`. Activity is a CLI command only. The MCP server has no tool for it.

## Event kinds

A Change is a state Sensei observed. It has no actor.

| `kind` | When it is recorded |
| --- | --- |
| `job_awaiting_response` | The agent asked a Clarification and is waiting for an answer. |
| `pr_checks_failed` | The checks on a session's pull request failed. |
| `pr_checks_passed` | The checks on a session's pull request passed. |
| `main_checks_failed` | A check suite failed on the repository's default branch, which no session owns. Recorded once per commit: `payload.headSha`, `payload.branch` and `payload.failedChecks` (each check's `name` and run `url`). |
| `main_checks_passed` | The default branch's head is green again after a recorded failure. `payload.failedHeadSha` is the commit that failed. |
| `pr_merged` | A session's pull request merged. `payload.mergedBy` names who merged it, when GitHub says. |
| `branch_behind` | A session's branch fell behind its Target Branch. |
| `cron_run_succeeded` | A Cron fired and its run succeeded. |
| `cron_run_failed` | A Cron's run failed. `payload.error` says why. |
| `deployed` | A project's first Deploy succeeded. `payload.deployJobId` and `payload.projectName` identify it. |
| `recovery_deploy_started` | Sensei started a Recovery Deploy after the first Deploy failed. `payload.deployJobId`, `payload.projectName` and `payload.failedDeployJobId` identify the transition. |
| `workspace_device_disconnected` | A workspace device was disconnected from the Mac itself, with Disconnect on its sign-in page. `payload.deviceId` and `payload.deviceName` identify it. |

A Member Action names the member who did it in `actor`.

| `kind` | When it is recorded |
| --- | --- |
| `session_started` | A member created a session and started it, or started a Backlog session. |
| `session_message_sent` | A member sent a message to a session. Recorded once per member, session and day. |
| `session_archived` | A member archived a session. |
| `session_deleted` | A member deleted a session. |
| `session_assigned` | A member set or cleared a session's Assignee, or filed a Backlog session for someone. |
| `session_status_changed` | A member moved a session to any status but Archived. `payload.from` and `payload.to` name the statuses. |
| `session_priority_changed` | A member changed a session's priority. |
| `session_moved` | A member moved a Todo task and its Backlog session to another repository of the workspace. The event is the destination's; `payload.fromProjectId` and `payload.fromProjectName` name the source, `payload.toProjectName` the destination. |
| `cron_created` | A member created a Cron. |
| `cron_updated` | A member edited, paused or resumed a Cron. `payload.change` says which. |
| `cron_deleted` | A member deleted a Cron. |
| `member_invited` | A member invited someone to the workspace. |
| `member_removed` | A member was removed, or left. `payload.self` is `true` when they left. |
| `member_role_changed` | A member's role changed. `payload.transfer` is `true` for an ownership transfer. |
| `integration_custom_tool_saved` | An admin saved a custom tool of a workspace integration: a first save (`payload.created` is `true`) or a new version. Personal custom tools write no event. |
| `integration_custom_tool_enabled` | An admin enabled a version of a custom tool. `payload.access` says whether it reads or writes. |
| `integration_custom_tool_disabled` | An admin disabled a custom tool. |
| `integration_custom_tool_deleted` | An admin deleted a custom tool. |
| `integration_custom_tool_restored` | An admin restored an earlier version of a custom tool as a new version. |

## Read only what is new

You have one Seen Mark per workspace. Every event after it is New to you, except your own actions. Two parameters read New events.

| Parameter | What it does |
| --- | --- |
| `unseen=true` | Returns your New events, oldest first, and leaves your Seen Mark where it is. |
| `markSeen=true` | Returns your New events, oldest first, and moves your Seen Mark past them in the same call. No event is returned twice. |

`markSeen` needs an API key. It works across every workspace, or in one with `workspace`. It cannot be combined with `project`, `kind` or `since`, because a Seen Mark covers a whole workspace. It ignores `cursor`. Call it again to read the next `limit` events.

```bash
curl -s "https://app.kosuke.ai/api/activity?markSeen=true&limit=20" \
  -H "Authorization: Bearer $KOSUKE_API_KEY"
```

In the CLI, run `kosuke activity list --unseen` to read without marking, or `kosuke activity list --mark-seen` to read and mark. `kosuke agent summary get` also marks seen the events it prints, unless you pass `--peek`. Opening Settings > your workspace > Activity in the web app marks that workspace's events seen too.

## Errors

| Status | Code | When |
| --- | --- | --- |
| 400 | `BAD_REQUEST` | A parameter has an invalid value, `kind` mixes a category with kinds, or `markSeen` was combined with `project`, `kind` or `since`. Also `markSeen` from a browser session. |
| 403 | `FORBIDDEN` | You are not a member of the `workspace` you named. |

The full list is in [Responses and errors](https://kosuke.ai/docs/api/errors.md).

## Next steps

- Find what needs you right now with `kosuke agent summary get` on [Sensei CLI](https://kosuke.ai/docs/interfaces/cli.md).
- Read or change the sessions an event names with [Chat sessions](https://kosuke.ai/docs/endpoint-reference/chat-sessions.md).
