Query chats

Fetch chats three ways - one by ID, an offset-paginated org-wide list, or a cursor-paginated list scoped to a single workspace you belong to.


Chats are standalone, workspace-scoped conversation threads (the Chat type). There are three read paths, and which one you reach for depends on what you have and what you need:

  • chat(id) — fetch a single thread by ID.
  • chats(filter, sort, skip, take) — the offset-paginated list across the current organization, filtered to one workspace and ordered by ChatSort (recently updated or recently commented).
  • chatList(projectId, ...) — the cursor-paginated variant scoped to one workspace, which returns only threads in workspaces you are a member of.

All three return the thread’s metadata (title, body, members, commentCount, read state) but not its replies. The messages inside a chat are Comment rows with category: DISCUSSION; load them separately with commentList. Use chat(id) to render a single thread, chats when you want simple page-number paging, and chatList when you want to walk a workspace’s threads with an opaque cursor.

Legacy names. Chat was called Discussion, and these three queries were discussion / discussions / discussionList. Every legacy name still works and returns identical data — it is marked @deprecated in introspection and points at its modern replacement. CommentCategory.DISCUSSION is not renamed: it is a stored enum value on millions of comment rows.

chat(id)

Use chat to fetch one thread by its ID.

Request

query GetChat {
  chat(id: "chat_123") {
    id
    title
    text
    commentCount
    createdAt
    user {
      id
      fullName
    }
    project {
      id
      name
    }
  }
}

Parameters

ParameterTypeRequiredDescription
idString!YesThe ID of the chat to load.

Response

{
  "data": {
    "chat": {
      "id": "clm4n8qwx000008l0g4oxdqn7",
      "title": "Q3 launch retro",
      "text": "What worked, what didn't, and what we change next quarter.",
      "commentCount": 14,
      "createdAt": "2026-05-20T09:12:44.000Z",
      "user": {
        "id": "clm4n8qwx000108l0a1b2c3d4",
        "fullName": "Dana Okafor"
      },
      "project": {
        "id": "clm4n8qwx000208l0e5f6g7h8",
        "name": "Marketing"
      }
    }
  }
}

Returns a single Chat. The query throws CHAT_NOT_FOUND when no thread matches the ID.

chats

Use chats for the offset-paginated list. It is filtered to a single workspace (via the required ChatFilterInput) but always scoped to the calling organization, so a projectId from another organization returns no results. Results default to most-recently-updated first.

Request

query ListChats {
  chats(filter: { projectId: "workspace_123" }, sort: [lastCommentedAt_DESC], skip: 0, take: 20) {
    items {
      id
      title
      commentCount
      updatedAt
    }
    pageInfo {
      totalItems
      totalPages
      page
      perPage
      hasNextPage
      hasPreviousPage
    }
  }
}

Parameters

ParameterTypeRequiredDefaultDescription
filterChatFilterInput!YesWhich workspace’s chats to return. See ChatFilterInput.
sort[ChatSort!]No[updatedAt_DESC]Sort order. See ChatSort.
skipIntNo0Number of chats to skip from the start of the result set.
takeIntNo20Maximum number of chats to return on this page.

ChatFilterInput

FieldTypeRequiredDescription
projectIdString!YesThe ID of the workspace whose chats to list.

ChatSort

sort takes a list of ChatSort values. Pass a single value for a single ordering.

ValueOrders by
updatedAt_DESCMost recently updated thread first (the default).
updatedAt_ASCLeast recently updated thread first.
lastCommentedAt_DESCThread with the most recent reply first.
lastCommentedAt_ASCThread with the oldest most-recent reply first.

Response

chats returns a ChatPagination — the threads on this page in items, plus offset pagination metadata in pageInfo.

{
  "data": {
    "chats": {
      "items": [
        {
          "id": "clm4n8qwx000008l0g4oxdqn7",
          "title": "Q3 launch retro",
          "commentCount": 14,
          "updatedAt": "2026-05-28T16:40:02.000Z"
        },
        {
          "id": "clm4n8qwx000308l0i9j0k1l2",
          "title": "Brand refresh kickoff",
          "commentCount": 3,
          "updatedAt": "2026-05-27T11:05:18.000Z"
        }
      ],
      "pageInfo": {
        "totalItems": 42,
        "totalPages": 3,
        "page": 1,
        "perPage": 20,
        "hasNextPage": true,
        "hasPreviousPage": false
      }
    }
  }
}

ChatPagination

FieldTypeDescription
items[Chat!]!The chats on this page.
pageInfoPageInfo!Offset pagination metadata for the result set.

To page through results, advance skip by take (for example skip: 20, take: 20 for the second page) until pageInfo.hasNextPage is false.

chatList

Use chatList for cursor-paginated access to one workspace’s threads. Unlike chats, it returns only threads in a workspace the caller is a member of — if you are not a member of projectId, the list comes back empty. Step through pages with the after cursor rather than a skip offset.

Request

query ListWorkspaceChats {
  chatList(projectId: "workspace_123", first: 20, orderBy: updatedAt_DESC) {
    discussions {
      id
      title
      commentCount
      updatedAt
    }
    totalCount
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}

Parameters

ParameterTypeRequiredDefaultDescription
projectIdString!YesThe workspace whose chats to list. Only returns threads if the caller is a workspace member.
firstIntNo20Maximum number of chats to return on this page.
afterStringNoCursor to page forward from — pass the previous page’s pageInfo.endCursor.
beforeStringNoCursor to page backward from.
lastIntNoMaximum number of chats to return when paging backward.
skipIntNo0Number of chats to skip. Reported in pageInfo; prefer after for forward paging.
orderByChatOrderByInputNoSort order. See ChatOrderByInput.

ChatOrderByInput

A single enum value of the form <field>_<direction>. The fields and directions available:

FieldAscendingDescending
idid_ASCid_DESC
uiduid_ASCuid_DESC
titletitle_ASCtitle_DESC
htmlhtml_ASChtml_DESC
texttext_ASCtext_DESC
createdAtcreatedAt_ASCcreatedAt_DESC
updatedAtupdatedAt_ASCupdatedAt_DESC

Response

chatList returns a ChatList — the threads in discussions, a totalCount of all matching threads, and a pageInfo carrying the endCursor for the next page.

{
  "data": {
    "chatList": {
      "discussions": [
        {
          "id": "clm4n8qwx000008l0g4oxdqn7",
          "title": "Q3 launch retro",
          "commentCount": 14,
          "updatedAt": "2026-05-28T16:40:02.000Z"
        }
      ],
      "totalCount": 42,
      "pageInfo": {
        "hasNextPage": true,
        "endCursor": "clm4n8qwx000008l0g4oxdqn7"
      }
    }
  }
}

ChatList

FieldTypeDescription
discussions[Chat!]!The chats on this page. Keeps its legacy name — wrapper types have no resolver to delegate a field rename through.
totalCountInt!Total number of chats in the workspace the caller can see.
pageInfoPageInfo!Cursor pagination metadata. endCursor is the ID of the last thread returned.

To fetch the next page, pass the current page’s pageInfo.endCursor as the next call’s after, and stop when pageInfo.hasNextPage is false.

The Chat type

All three queries return the same Chat shape. Replies are not included here — load them with commentList.

FieldTypeDescription
idID!Unique identifier for the chat.
titleString!The thread title.
descriptionStringOptional short description.
htmlString!The opening body as sanitized HTML.
textString!The opening body as plain text.
kindChatKind!CHANNEL for the workspace threads this page’s chats/chatList return. chat(id) can also return a DM or GROUP conversation — see Direct Messages & Group Chats.
createdAtDateTime!When the chat was created.
updatedAtDateTime!When the chat was last updated.
userUser!The thread’s creator. Select id, fullName, email.
people[User!]Members of the chat.
projectWorkspaceThe workspace the chat belongs to. null for the DM/GROUP kinds, which have no workspace.
members[ChatMember!]!Membership rows for DM/GROUP conversations. Empty for CHANNEL.
commentCountInt!Number of replies in the thread.
isReadBooleanWhether the calling user has read this chat. Evaluated per caller.
isSeenBooleanWhether the calling user has seen this chat. Evaluated per caller.

Loading a thread’s replies

A chat query gives you the thread; to render the conversation, follow up with commentList scoped to that chat. commentList returns only top-level comments — read each comment’s replies for the threaded answers.

query ChatWithComments {
  chat(id: "chat_123") {
    id
    title
    commentCount
  }
  commentList(category: DISCUSSION, categoryId: "chat_123", first: 20) {
    comments {
      id
      text
      user {
        id
        fullName
      }
      replyCount
    }
    totalCount
  }
}

Errors

CodeWhen
CHAT_NOT_FOUNDchat(id) — no chat matches the given ID.
FORBIDDENchat(id) — the caller can’t view this thread (not a member of its workspace for CHANNEL, or no membership row for DM/GROUP).
UNAUTHENTICATEDThe request carries no valid authentication.

Permissions

  • chat(id) is not scoped by organization or workspace at the shield layer — it works for a plain client/DM-only user with no resolvable workspace. Access is resolved per thread kind: CHANNEL requires workspace membership, DM/GROUP requires a ChatMember row (including a removed one — see Direct Messages & Group Chats). Either case failing throws FORBIDDEN.
  • chats returns threads only for the calling organization. A projectId belonging to another organization yields an empty items list rather than an error.
  • chatList returns threads only for projects the caller is a member of. Passing a projectId you do not belong to returns an empty discussions list, not an error.

All three calls authenticate with the standard token headers (blue-token-id, blue-token-secret, blue-org-id). The organization and project arguments accept an ID or a slug. chats and chatList only ever return CHANNEL threads, since their filters require a projectId; only chat(id) can return a DM/GROUP conversation.