Comments, Discussions & Chat

Real-time GraphQL subscriptions for comments, typing indicators, discussions, status updates, AI chat, and collaborative documents.


These subscriptions stream the conversational surfaces of a workspace: comments on records, discussions, and status updates; the typing indicators that appear while someone is writing; the AI chat assistant; and collaborative documents. Open one over the same authenticated WebSocket you use for every other subscription — see Connect & Authenticate for the graphql-ws handshake. The endpoint is wss://api.blue.cc/graphql.

Workspaces are Project objects in the API, and records are Todo objects. Comments, discussions, and status updates all live inside a workspace, so every subscription here is scoped by a projectId (or, for subscribeToComment, the ID of the thing being commented on).

Shared payload shape

The entity subscriptions on this page (subscribeToComment, subscribeToDiscussion, subscribeToStatusUpdate, subscribeToDocument) deliver the standard change-feed payload — { mutation, node, previousValues, updatedFields } where mutation is CREATED, UPDATED, or DELETED. That shape is documented once on the Real-time overview. subscribeToChat and subscribeToCommentTyping deviate; both are called out below.

subscribeToComment

Streams comment changes (create, edit, delete) for one thread. A thread is identified by a category and the ID of the parent it hangs off — a discussion, a status update, or a record.

Request

subscription OnRecordComments {
  subscribeToComment(category: TODO, categoryId: "todo_123") {
    mutation
    node {
      id
      html
      text
      user {
        id
        fullName
      }
      parentId
      replyCount
      createdAt
    }
    updatedFields
  }
}

Parameters

ArgumentTypeRequiredDescription
categoryCommentCategory!YesWhich kind of parent the comments belong to. See the enum below.
categoryIdString!YesThe ID of the parent — a Discussion ID, a StatusUpdate ID, or a Todo ID, matching category.
showOnlyMentionedCommentsBooleanNoWhen true, deliver only comments where you are the mentioner or the mentionee. The category/categoryId filter is then ignored. Defaults to false.

CommentCategory

ValueParent typecategoryId is the ID of
DISCUSSIONDiscussionA discussion thread
STATUS_UPDATEStatusUpdateA status update
TODOTodoA record

Response

{
  "data": {
    "subscribeToComment": {
      "mutation": "CREATED",
      "node": {
        "id": "clm4n8qwx000008l0g4oxdqn7",
        "html": "<p>Looks good — shipping it.</p>",
        "text": "Looks good — shipping it.",
        "user": { "id": "clm4n8qwx000108l0a1b2c3d4", "fullName": "Ada Lovelace" },
        "parentId": null,
        "replyCount": 0,
        "createdAt": "2026-05-29T14:02:11.000Z"
      },
      "updatedFields": []
    }
  }
}

Returns — CommentSubscriptionPayload

FieldTypeDescription
mutationMutationType!CREATED, UPDATED, or DELETED.
nodeCommentThe comment after the change. null for some DELETED events.
previousValuesCommentPreviousValuesThe comment’s prior state on an UPDATED/DELETED event.
updatedFields[String!]Names of the Comment fields that changed on an UPDATED event.

A Comment exposes id, html, text, category, user, parent/parentId, replies, replyCount, reactions, isRead, isSeen, createdAt, and updatedAt, plus the discussion/statusUpdate/todo it belongs to.

Mentions-only mode

Set showOnlyMentionedComments: true to receive comments across any thread where you were @-mentioned (or where you authored the mention), regardless of category/categoryId:

subscription OnMyMentionedComments {
  subscribeToComment(category: TODO, categoryId: "todo_123", showOnlyMentionedComments: true) {
    mutation
    node {
      id
      text
      todo {
        id
        title
      }
    }
  }
}

category and categoryId are still required by the schema, but the resolver bypasses them in this mode — pass any valid values.

Errors

CodeWhen
UNAUTHENTICATEDThe WebSocket handshake carried no valid credentials.

Permissions

Subscribing always succeeds. You only receive events for comments you can see — the resolver matches each published comment against your category/categoryId filter (or your mentions) before delivering it.


subscribeToCommentTyping

Streams typing indicators for one thread: each event is the User who is currently typing into that discussion, status update, or record. This is how the app renders “Ada is typing…” beneath a comment box.

The producer side is the commentTyping mutation, which a client calls (debounced) while its user types. That publish fans out to everyone subscribed to the same thread.

Request

subscription OnDiscussionTyping {
  subscribeToCommentTyping(id: "discussion_123", name: DISCUSSION) {
    id
    fullName
  }
}

Parameters

ArgumentTypeRequiredDescription
idString!YesThe thread ID — a Discussion, StatusUpdate, or Todo ID, matching name.
nameCommentTypingSubscriptionNameNoWhich thread surface to watch. Pair it with the matching id.

CommentTypingSubscriptionName

Valueid is the ID of
DISCUSSIONA discussion thread
STATUS_UPDATEA status update
TODOA record

Response

This subscription returns a bare User!, not a change-feed payload — there is no mutation or node wrapper. Each event is the typing user.

{
  "data": {
    "subscribeToCommentTyping": {
      "id": "clm4n8qwx000208l0e5f6g7h8",
      "fullName": "Grace Hopper"
    }
  }
}

Permissions

Events are keyed strictly by thread (name + id), so you receive typing pings only for threads you actively subscribe to. Subscribe to the same thread you are reading comments from.


subscribeToDiscussion

Streams discussion lifecycle changes (created, edited, deleted) within a workspace. Use it to keep a discussion list live as threads are opened and renamed.

Request

subscription OnDiscussions {
  subscribeToDiscussion(projectId: "project_123") {
    mutation
    node {
      id
      title
      html
      commentCount
      user {
        id
        fullName
      }
      updatedAt
    }
    updatedFields
  }
}

Parameters

ArgumentTypeRequiredDescription
projectIdString!YesThe workspace whose discussions you want to watch.

Response

{
  "data": {
    "subscribeToDiscussion": {
      "mutation": "UPDATED",
      "node": {
        "id": "clm4n8qwx000308l0i9j0k1l2",
        "title": "Q3 launch checklist",
        "html": "<p>Final review before we ship.</p>",
        "commentCount": 4,
        "user": { "id": "clm4n8qwx000108l0a1b2c3d4", "fullName": "Ada Lovelace" },
        "updatedAt": "2026-05-29T14:05:40.000Z"
      },
      "updatedFields": ["title"]
    }
  }
}

Returns — DiscussionSubscriptionPayload

FieldTypeDescription
mutationMutationType!CREATED, UPDATED, or DELETED.
nodeDiscussionThe discussion after the change.
previousValuesDiscussionPreviousValuesPrior state on UPDATED/DELETED.
updatedFields[String!]Field names that changed on UPDATED.

Errors

CodeWhen
UNAUTHENTICATEDThe WebSocket handshake carried no valid credentials.

Permissions

You only receive events for the workspace if you are a member of it. Events for workspaces you do not belong to are filtered out before delivery.


subscribeToStatusUpdate

Streams status update changes within a workspace — the posts that appear in a workspace’s status feed.

Request

subscription OnStatusUpdates {
  subscribeToStatusUpdate(projectId: "project_123") {
    mutation
    node {
      id
      html
      text
      date
      category
      user {
        id
        fullName
      }
    }
    updatedFields
  }
}

Parameters

ArgumentTypeRequiredDescription
projectIdString!YesThe workspace whose status updates you want to watch.

Response

{
  "data": {
    "subscribeToStatusUpdate": {
      "mutation": "CREATED",
      "node": {
        "id": "clm4n8qwx000408l0m3n4o5p6",
        "html": "<p>On track for Friday.</p>",
        "text": "On track for Friday.",
        "date": "2026-05-29T00:00:00.000Z",
        "category": "GREEN",
        "user": { "id": "clm4n8qwx000108l0a1b2c3d4", "fullName": "Ada Lovelace" }
      },
      "updatedFields": []
    }
  }
}

Returns — StatusUpdateSubscriptionPayload

FieldTypeDescription
mutationMutationType!CREATED, UPDATED, or DELETED.
nodeStatusUpdateThe status update after the change.
previousValuesStatusUpdatePreviousValuesPrior state on UPDATED/DELETED.
updatedFields[String!]Field names that changed on UPDATED.

Errors

CodeWhen
UNAUTHENTICATEDThe WebSocket handshake carried no valid credentials.

Permissions

Delivered only for workspaces you belong to: the resolver matches the published workspace ID against projectId and confirms you are a member before forwarding the event.


subscribeToChat

Streams the AI chat assistant’s conversation changes (Chat objects) for a workspace — new chats, renames, and deletions. Use it to keep a chat sidebar in sync as conversations are created and updated.

Request

subscription OnChats {
  subscribeToChat(filter: { projectId: "project_123" }) {
    mutation
    node {
      id
      title
      type
      messages {
        id
        text
        createdBy {
          id
          fullName
        }
      }
      updatedAt
    }
  }
}

Parameters

SubscribeToChatFilterInput

ParameterTypeRequiredDescription
projectIdString!YesThe workspace whose chats you want to watch.

Response

{
  "data": {
    "subscribeToChat": {
      "mutation": "CREATED",
      "node": {
        "id": "clm4n8qwx000508l0q7r8s9t0",
        "title": "Summarize this workspace",
        "type": "PROJECT_ASSISTANT",
        "messages": [],
        "updatedAt": "2026-05-29T14:08:02.000Z"
      }
    }
  }
}

Returns — ChatSubscriptionPayload

FieldTypeDescription
mutationMutationType!CREATED, UPDATED, or DELETED.
nodeChatThe chat after the change.
previousValuesChatThe chat’s prior state.
No updatedFields on chat

ChatSubscriptionPayload does not include the updatedFields array that the other entity payloads carry, and its previousValues is a full Chat (not a separate *PreviousValues type). Do not select updatedFields here — it is not a field on this payload.

Errors

CodeWhen
UNAUTHENTICATEDThe WebSocket handshake carried no valid credentials.

Permissions

Events are matched on filter.projectId, so you receive chat changes for the requested workspace.


subscribeToDocument

Streams collaborative document changes (Document objects) within a workspace — created, edited, deleted. Optionally narrow to wiki documents only.

Request

subscription OnDocuments {
  subscribeToDocument(input: { projectId: "project_123" }) {
    mutation
    node {
      id
      title
      wiki
      createdBy {
        id
        fullName
      }
      updatedAt
    }
    updatedFields
  }
}

Parameters

SubscribeToDocumentInput

ParameterTypeRequiredDescription
projectIdString!YesThe workspace whose documents you want to watch.
wikiBooleanNoWhen set, deliver only documents whose wiki flag matches this value — true for wiki pages, false for regular documents. Omit to receive both.

Response

{
  "data": {
    "subscribeToDocument": {
      "mutation": "UPDATED",
      "node": {
        "id": "clm4n8qwx000608l0u1v2w3x4",
        "title": "Onboarding runbook",
        "wiki": true,
        "createdBy": { "id": "clm4n8qwx000108l0a1b2c3d4", "fullName": "Ada Lovelace" },
        "updatedAt": "2026-05-29T14:11:27.000Z"
      },
      "updatedFields": ["title"]
    }
  }
}

Returns — DocumentSubscriptionPayload

FieldTypeDescription
mutationMutationType!CREATED, UPDATED, or DELETED.
nodeDocumentThe document after the change. Exposes id, title, content, contentBase64, wiki, project, createdBy, createdAt, updatedAt.
previousValuesDocumentPreviousValuesPrior state on UPDATED/DELETED.
updatedFields[String!]Field names that changed on UPDATED.
Document metadata vs. live editing

subscribeToDocument reports document-level changes (title, wiki flag, create/delete). It is not the character-by-character editing channel — live collaborative editing runs over a separate Hocuspocus connection at /collab, not the GraphQL WebSocket.

Errors

CodeWhen
UNAUTHENTICATEDThe WebSocket handshake carried no valid credentials.

Permissions

Delivered only for workspaces you belong to. When wiki is supplied, only documents matching that flag are forwarded; otherwise both wiki and non-wiki documents stream through.