---
title: "List Chats"
method: GET
path: "/api/chats"
tags: ["chats"]
---

# List Chats

`GET /api/chats`

## Request

- Base URL: `https://app.thinqos.com` (the document declares no server; this is the origin it was published from)
- URL: `https://app.thinqos.com/api/chats`
- Auth: none declared

List chats where the current identity is an active participant.

Keyset-paginated, search-aware, and filterable:

- ``?archived=true`` lists chats the caller has archived.
- ``?unread_only=true`` filters to chats with unread messages, excluding
  effectively-muted chats (TOS-575; resolved in SQL per TOS-634).
- ``?q=<text>`` filters to chats whose title or any active participant's
  display name matches (case-insensitive substring), across the caller's
  entire chat history rather than the first page.
- ``?cursor=<token>`` resumes after a previous page. The token for the next
  page (``None`` on the last page) is returned in the ``X-Next-Cursor``
  response header so the JSON body stays a plain list.
- ``?needs_you_only=true`` (TOS-7692) keeps only chats whose ``needs_you``
  is set. It composes with every other filter and with the cursor.

TOS-7692: every row carries ``last_message_preview``, ``needs_you`` and
``working`` (see services/chats/list_signals.py for their sources), and the
``X-Needs-You-Count`` header counts the caller's chats that need them in
the requested archive state, ignoring every other filter. Both ride the
existing list statements; neither adds a round trip.

TOS-2596 filter axes. Every one of these used to be applied in the browser
to whatever page was already loaded, so a filter hid rows instead of
running a query - selecting a capture source the caller owned 991
conversations from returned nothing, because none were on page one, and
infinite scroll had to be disabled whenever a filter was active. As query
params they compose with the cursor, so a page holds ``limit`` matches:

- ``?source=<slug>`` restricts to one capture source; the reserved value
  ``thinqos`` selects native conversations (no capture source).
- ``?capture_connection_id=<uuid>`` narrows to one connection/deployment.
- ``?capture_org_id=<external org id>`` narrows to one customer ORG across
  every connection the caller has for it. Use this, not
  ``capture_connection_id``, for a user-facing "conversations from <org>"
  filter: one customer reached through two deployments is two connection
  rows for the same caller, so a per-connection filter returns part of that
  customer's history while looking complete.
- ``?origin=<slug>&origin=<slug>|<external org id>&origin=thinqos`` (TOS-4379)
  selects SEVERAL origins at once, OR'd: a whole source, one customer
  org of an org-scoped source (``slug|org``), or native conversations.
  When present it supersedes ``source`` and ``capture_org_id``.
- ``?pinned_only=true``.
- ``?kinds=direct&kinds=room&...`` OR's the conversation kinds
  (``direct``, ``room``, ``topic``, ``agent``, ``people``).
- ``?activity_since=<iso8601>`` bounds by last activity. Send an absolute
  instant so "Today"/"This week" resolve in the CALLER's timezone.
- ``?participant_identity_id=<uuid>`` narrows to chats that identity is
  ALSO in (TOS-3292) - an intersection with the caller's own participation,
  so it can only remove rows. Used by the agent schedule picker to list the
  chats an agent can be scheduled into.

TOS-2216: the retired ``?surface=history`` split (a separate view of
concluded conversations) is gone. ``concluded_at`` may still be set
internally (see ``ChatService.conclude_chat``/``reopen_chat``) but no
longer excludes a chat from this list - the only user-visible axes are
read/unread and archived/unarchived, both participant scoped.

## Query parameters

- `archived` boolean
- `unread_only` boolean
- `needs_you_only` boolean
- `q` string, nullable
- `cursor` string, nullable
- `limit` integer
- `source` string, nullable
- `capture_connection_id` string, uuid, nullable
- `capture_org_id` string, nullable
- `origin` string[], nullable
- `pinned_only` boolean
- `kinds` string[], nullable
- `activity_since` string, date-time, nullable
- `participant_identity_id` string, uuid, nullable

## Headers

- `x-impersonate-identity-id` string, nullable

## Response `200`

Successful Response

- ChatResponse[]
  - `id` string, uuid, required
  - `title` string, nullable, required
  - `container_kind` string, required
  - `status` string, required
  - `description` string, nullable
  - `root_container_id` string, uuid, nullable
  - `topic_parent_id` string, uuid, nullable
  - `is_pinned` boolean
  - `extraction_excluded` boolean
  - `mind_context_disabled` boolean
  - `tenant_id` string, uuid, nullable
  - `tenant_name` string, nullable
  - `tenant_is_org` boolean
  - `message_count` integer, required
  - `message_count_capped` boolean
  - `unread_count` integer
  - `last_message_at` string, date-time, nullable, required
  - `started_at` string, date-time, nullable, required
  - `has_active_recipients` boolean
  - `facilitation_mode` 'natural' | 'facilitated'
  - `facilitator_identity_id` string, uuid, nullable
  - `alternate_facilitator_identity_ids` string[]
  - `max_responders` integer
  - `max_chain_depth` integer
  - `top_k_claimants` integer
  - `max_concurrent_generations` integer
  - `max_concurrent_generations_per_provider` integer
  - `max_root_container_spend_usd` number, nullable
  - `participant_count` integer
  - `participants` ParticipantPreview[]
    - `identity_id` string, uuid, required
    - `display_name` string, required
    - `avatar_url` string, nullable, required
    - `kind` 'person' | 'agent' | 'org', required
  - `viewer_role` string, nullable
  - `viewer_can_delete` boolean
  - `default_agent` ParticipantPreview
    - `identity_id` string, uuid, required
    - `display_name` string, required
    - `avatar_url` string, nullable, required
    - `kind` 'person' | 'agent' | 'org', required
  - `muted` boolean
  - `group_key` string, nullable
  - `display_title` string, nullable
  - `display_subtitle` string, nullable
  - `lifecycle` 'live' | 'concluded'
  - `concluded_at` string, date-time, nullable
  - `source` string, nullable
  - `source_display_name` string, nullable
  - `source_icon_url` string, nullable
  - `source_recognized` boolean, nullable
  - `capture_connection_id` string, uuid, nullable
  - `conversation_kind` 'DIRECT' | 'ROOM' | 'TOPIC' | 'RUN' | 'CAPTURE' | 'ASSISTANT', nullable
  - `is_person_conversation` boolean
  - `last_message_preview` ChatLastMessagePreview: TOS-7692: the latest visible message, flattened to plain text (<=140 chars).
    - `sender_name` string, nullable
    - `sender_is_viewer` boolean
    - `text` string, required
  - `needs_you` ChatNeedsYou: TOS-7692: why the chat is waiting on the viewer, from structured state.
    - `reason` 'approval' | 'input' | 'failed' | 'question' | 'mention', required
    - `since` string, date-time, required
  - `working` ChatWorking: TOS-7692: an agent turn or run in the chat is in progress right now.
    - `started_at` string, date-time, required
    - `label` string, nullable

## Other responses

- `422`: Validation Error

## Changes

- **2026-10-20** `5387b4ded614`: 1 info
  - added the optional property `items/viewer_can_delete` to the response with the `200` status

[Operation history](https://skmtc.dev/thinqos/apis/thinqos-api/changes/api/chats/get.md)

---

[API](https://skmtc.dev/thinqos/apis/thinqos-api.md) · [All operations](https://skmtc.dev/thinqos/apis/thinqos-api/llms.txt) · [OpenAPI document](https://skmtc.dev/thinqos/apis/thinqos-api/revisions/5fdd1072e877?raw)
