---
title: "Search or list unified sessions"
method: GET
path: "/projects/{projectId}/sessions"
tags: ["Catalog"]
---

# Search or list unified sessions

`GET /projects/{projectId}/sessions`

The unified, cross-surface sessions feed for one project: Playground, user-testing, eval, and swarm transcripts in one list, newest first. Project-NESTED (unlike `/chat-sessions`) because `projectId` owns the scope here rather than filtering it.

Supplying `q` at all switches to relevance-ordered search; `scope` then chooses what is searched. Row-level visibility applies in every mode: a caller never receives another member's private Playground session.

The response echoes the honored `scope`. A deployment predating that parameter omits the echo — clients requesting a non-default scope MUST treat its absence as "unsupported" rather than accepting the results.

## Path parameters

- `projectId` string, required

## Query parameters

- `q` string
- `scope` 'titles' | 'transcripts'
- `sourceType` string
- `status` 'active' | 'archived'
- `limit` integer
- `cursor` string

## Response `200`

One page of sessions — newest first when listing, most relevant first when searching.

- SessionSummaryPage
  - `items` SessionSummary[], required
    - `id` string, required
    - `chatSessionId` string, required — Wire id used by the Playground restore; distinct from `id`.
    - `projectId` string, nullable, required
    - `sourceType` 'direct' | 'chatbox' | 'eval' | 'swarm', required
    - `origin` string, nullable, required
    - `status` string, required
    - `synthetic` boolean, required
    - `lockReason` string, nullable, required
    - `title` string, nullable, required
    - `firstMessagePreview` string, required
    - `visibility` string, nullable, required — Direct sessions only: `private` or `project`. Null elsewhere.
    - `ownedByViewer` boolean, required
    - `startedAt` integer, required
    - `lastActivityAt` integer, required
    - `modelId` string, nullable, required
    - `messageCount` integer, required
    - `cumulativeUserMessageCount` integer — Absent (not 0) when the session never reported the counter.
    - `cumulativeToolCallCount` integer
    - `cumulativeInputTokens` integer
    - `cumulativeOutputTokens` integer
    - `parentRef` SessionParentRef, required — The session's parent run, discriminated on `kind`. Additive: switch on `kind` and tolerate an unknown value.
      - `kind` 'evalRun' | 'journeyRun' | 'chatbox', required
      - `label` string, nullable, required — Human-readable parent name; null when the parent row is gone.
      - `iterationId` string
      - `suiteRunId` string, nullable — eval only; null means Quick Run (no suite run exists).
      - `suiteId` string, nullable
      - `journeyRunId` string
      - `journeyRefId` string, nullable
      - `chatboxId` string
    - `link` SessionLink, required — Where a human goes to read this session. Prefers the surface-native page; falls back to `/sessions?session=` when the session has none (an eval Quick Run, or a deleted parent run).
      - `path` string, required — App-relative path, including `?project=`.
      - `url` string, required — Absolute URL for the same target.
    - `matchPreview` string, nullable — `scope=transcripts` only: a window of the transcript around the match. Null when no window could be located; absent entirely on title-scope results.
  - `nextCursor` string — Pass as `cursor` to fetch the next page. Omitted on the last page.
  - `scope` 'titles' | 'transcripts' — The scope the server actually honored. ABSENT from deployments predating the parameter — treat its absence as "transcript search unsupported".

## Other responses

- `400` — Malformed body or parameters.
- `401` — Missing, invalid, revoked, or orphaned key (`UNAUTHORIZED`) — or the **target MCP server** needs an OAuth grant (`OAUTH_REQUIRED`), which is a property of the server, not your key.
- `403` — Key is valid but not allowed to do this.
- `404` — Unknown project, server, or resource.
- `429` — Per-key rate limit exceeded (60 requests/minute sustained, bursts up to 10). Honor `Retry-After` and back off with jitter.
- `500` — Something failed on MCPJam's side.
- `502` — Could not connect to the target MCP server.

---

[API](https://skmtc.net/mcpjam/apis/mcpjam-api.md) · [All operations](https://skmtc.net/mcpjam/apis/mcpjam-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/mcpjam/mcpjam-api/revisions/7d1aff84ce3b/schema)
