Query and subscribe to status updates

Fetch a status update by id, list a workspace's updates with filtering, ordering, and cursor pagination, and subscribe to real-time create and delete events.


Read status updates with two queries and one subscription. Use the statusUpdate query to fetch a single update by id, the statusUpdateList query to page through a workspace’s updates with user and date filtering plus ordering, and the subscribeToStatusUpdate subscription to receive create and delete events in real time. Status updates are StatusUpdate objects in the API; in the app they appear as the colored health check-ins on a workspace (a Project).

The StatusUpdate type, the StatusUpdateCategory health enum, and the immutability rule (there is no edit operation) are documented once on the section overview. To create or delete updates, see Post and delete status updates.

Fetch one status update

Use statusUpdate(id: String!): StatusUpdate! to read a single update. The return type is non-null — a missing id raises STATUS_UPDATE_NOT_FOUND rather than returning null.

Request

query GetStatusUpdate {
  statusUpdate(id: "status_update_123") {
    id
    category
    html
    text
    date
    commentCount
    user {
      id
      fullName
      email
    }
    project {
      id
      name
    }
    createdAt
    updatedAt
  }
}

Parameters

ArgumentTypeRequiredDescription
idString!YesThe id of the status update to read.

Response

{
  "data": {
    "statusUpdate": {
      "id": "clm4n8qwx000008l0g4oxdqn7",
      "category": "GREEN",
      "html": "<p>Sprint is on track — all critical paths green.</p>",
      "text": "Sprint is on track — all critical paths green.",
      "date": "2026-05-29T00:00:00.000Z",
      "commentCount": 2,
      "user": {
        "id": "clm4n8qwx000108l0haz1f2pe",
        "fullName": "Dana Reyes",
        "email": "[email protected]"
      },
      "project": {
        "id": "clm4n8qwx000208l0c1d2e3f4",
        "name": "Q3 Launch"
      },
      "createdAt": "2026-05-29T14:02:11.000Z",
      "updatedAt": "2026-05-29T14:02:11.000Z"
    }
  }
}

StatusUpdate

The fields you’ll select most often. The full type is documented on the section overview.

FieldTypeDescription
idID!Unique identifier.
htmlString!Commentary as sanitized rich-text HTML.
textString!Commentary as plain text — the fallback for the same body as html.
dateDateTime!The reporting date the update is for. Distinct from createdAt — the UI lets you backdate it.
categoryStatusUpdateCategory!The health signal: GREEN, ORANGE, or RED.
userUser!The author. Select id, fullName, email (a User has no name).
projectProject!The workspace this update belongs to.
commentCountInt!Number of comments on this update.
isReadBooleanWhether the calling user has read this update.
isSeenBooleanWhether the calling user has seen this update in the feed.
createdAtDateTime!When the update was posted.
updatedAtDateTime!When the row was last touched.
Reading comments

StatusUpdate.comments is deprecated — read comments with the comment operations instead (a Comment with category: STATUS_UPDATE and categoryId set to the update’s id). The commentCount field above is the supported way to get the count inline.

List a workspace’s status updates

Use statusUpdateList to page through every status update in one workspace, optionally narrowed to a single author or a reporting-date range. The query returns a StatusUpdateList envelope: the page of updates plus pagination metadata and a total count.

Request

projectId is the only required argument. Without an orderBy, results come back newest-first by creation date.

query ListStatusUpdates {
  statusUpdateList(projectId: "project_123") {
    statusUpdates {
      id
      category
      date
      user {
        id
        fullName
      }
    }
    pageInfo {
      totalItems
      hasNextPage
      endCursor
    }
    totalCount
  }
}

The projectId accepts a workspace ID or slug.

Parameters

ArgumentTypeRequiredDescription
projectIdString!YesThe workspace whose updates to list (ID or slug).
userIdStringNoReturn only updates authored by this exact user.
dateFromDateTimeNoLower bound (inclusive) on the update’s reporting date.
dateToDateTimeNoUpper bound (inclusive) on the update’s reporting date.
firstIntNoPage size. Omit to get 20.
afterStringNoCursor for forward pagination — pass a previous page’s endCursor (the last item’s id) to fetch the next page.
beforeStringNoCursor for the relay-style pagination shape.
lastIntNoCompanion to before in the relay-style shape.
skipIntNoItems to skip — feeds the page / hasPreviousPage math in pageInfo. Defaults to 0.
orderByStatusUpdateOrderByInputNoSort key. Defaults to createdAt_DESC (newest first) when omitted.
Cursor pagination

statusUpdateList paginates by cursor, not by skip/limit. To walk the list, read pageInfo.endCursor from one page and pass it as after on the next call (the resolver sets the cursor to that id and skips it, so you get the rows that follow). Stop when pageInfo.hasNextPage is false.

StatusUpdateOrderByInput

Each value is a field_DIRECTION enum member.

ValueSorts by
createdAt_ASC / createdAt_DESCWhen the update was posted (default: createdAt_DESC).
date_ASC / date_DESCThe reporting date.
category_ASC / category_DESCHealth category.
updatedAt_ASC / updatedAt_DESCWhen the row was last touched.
html_ASC / html_DESCRich-text body.
text_ASC / text_DESCPlain-text body.
id_ASC / id_DESCInternal id.
uid_ASC / uid_DESCShort identifier.

Response

{
  "data": {
    "statusUpdateList": {
      "statusUpdates": [
        {
          "id": "clm4n8qwx000008l0g4oxdqn7",
          "category": "GREEN",
          "date": "2026-05-29T00:00:00.000Z",
          "user": {
            "id": "clm4n8qwx000108l0haz1f2pe",
            "fullName": "Dana Reyes"
          }
        },
        {
          "id": "clm4n8qwx000308l0g9h8i7j6",
          "category": "ORANGE",
          "date": "2026-05-22T00:00:00.000Z",
          "user": {
            "id": "clm4n8qwx000108l0haz1f2pe",
            "fullName": "Dana Reyes"
          }
        }
      ],
      "pageInfo": {
        "totalItems": 14,
        "hasNextPage": true,
        "endCursor": "clm4n8qwx000308l0g9h8i7j6"
      },
      "totalCount": 14
    }
  }
}

StatusUpdateList

FieldTypeDescription
statusUpdates[StatusUpdate!]!The updates on this page.
pageInfoPageInfo!Pagination metadata (below).
totalCountInt!Total updates matching the filter, across all pages.

PageInfo

FieldTypeDescription
totalItemsIntTotal updates matching the filter (mirrors totalCount).
totalPagesIntTotal pages at the current page size.
pageIntCurrent page, derived from skip and the page size.
perPageIntPage size in effect.
hasNextPageBoolean!Whether a next page exists.
hasPreviousPageBoolean!Whether a previous page exists.
endCursorStringThe last item’s id on this page. Pass it as after to fetch the next page.
startCursorStringDeprecated.

Full example

List the ORANGE and RED updates a single user reported across May 2026, oldest-first, ten per page.

query ListStatusUpdatesFiltered {
  statusUpdateList(
    projectId: "project_123"
    userId: "user_123"
    dateFrom: "2026-05-01T00:00:00Z"
    dateTo: "2026-05-31T23:59:59Z"
    orderBy: date_ASC
    first: 10
  ) {
    statusUpdates {
      id
      category
      html
      text
      date
      commentCount
      isRead
      user {
        id
        fullName
        email
      }
      createdAt
    }
    pageInfo {
      totalItems
      totalPages
      page
      perPage
      hasNextPage
      hasPreviousPage
      endCursor
    }
    totalCount
  }
}

The dateFrom / dateTo bounds filter the reporting date, not createdAt — so backdated updates are matched by the date they report for.

Subscribe to status updates

Use the subscribeToStatusUpdate(projectId: String!): StatusUpdateSubscriptionPayload subscription to receive an event whenever a status update is created or deleted in a workspace. Subscriptions run over WebSocket at wss://api.blue.cc/graphql.

Events are scoped to one workspace and delivered only to project members — the server filters each event by whether the subscriber is in that project’s user list. A non-member receives nothing.

Request

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

Parameters

ArgumentTypeRequiredDescription
projectIdString!YesThe workspace to receive status-update events for.

Payload

Each event is a StatusUpdateSubscriptionPayload.

FieldTypeDescription
mutationMutationType!The event kind: CREATED or DELETED. (See note below.)
nodeStatusUpdateThe affected status update. Populated on create; null once the row is gone on delete.
previousValuesStatusUpdatePreviousValuesThe prior scalar values (id, uid, html, text, date, category, createdAt, updatedAt). Useful on delete.
updatedFields[String!]Names of changed fields, when applicable.
Create and delete only

MutationType includes UPDATED, but the public API has no edit operation for status updates (they’re immutable — delete and re-create to change one), so in practice this subscription fires only CREATED and DELETED events. Don’t build on an UPDATED event arriving.

Example event

{
  "data": {
    "subscribeToStatusUpdate": {
      "mutation": "CREATED",
      "node": {
        "id": "clm4n8qwx000408l0k1l2m3n4",
        "category": "RED",
        "date": "2026-05-29T00:00:00.000Z",
        "html": "<p>Blocked on the vendor API outage.</p>",
        "user": {
          "id": "clm4n8qwx000108l0haz1f2pe",
          "fullName": "Dana Reyes"
        }
      },
      "previousValues": null,
      "updatedFields": null
    }
  }
}

Errors

CodeWhen
STATUS_UPDATE_NOT_FOUNDstatusUpdate(id) was called with an id that doesn’t exist.
UNAUTHENTICATEDThe request carries no valid credentials.
FORBIDDENThe token is valid but lacks access to the workspace or update.

Permissions

All three operations require an authenticated caller with access to the workspace the update belongs to. The subscribeToStatusUpdate subscription additionally filters events to project members only: the server checks that the subscriber is in the project’s user list before delivering each event, so a non-member’s subscription stays silent. There is no separate read role for status updates beyond workspace membership.