# HXP Threads and Listening for Changes
> Source: /hxp/threads-and-events
> Operator-only thread reads, event polling, pagination, message writes, and channel ingress

<Warning>
  All HTTP examples on this page require an authenticated HXP operator session and authorized workspace. They are not public integration endpoints. MCP has a separate, limited [tool contract](/hxp/operator-mcp).
</Warning>

For third-party server access, use the separate [organization API-key contract](/hxp/machine-integrations). Its read projections and allowed commands are narrower than the operator API documented below. Do not substitute its bearer key into these operator URLs.


## Read endpoints [#read-endpoints]

Base path: `/api/v1/orgs/{orgId}/messaging?scope={scopeId}`. Successful responses have a `{ "data": ... }` envelope and `Cache-Control: private, no-store`.

| Query | Response data | Pagination |
| --- | --- | --- |
| `view=thread&guest={guestId}` | `guestName`, `timeZone`, `stays`, `references`, `messages`, `actions`, `runs`, `legacy`, `actorId`, `canWrite`, `nextCursor` | Pass `nextCursor` as `before` for older messages |
| `view=inbox` (default) | Personal `items`, team `queues`, `actorId`, `nextCursor`, `queueNextCursor` | `before` for attention; `queueBefore` for the team queue; `snoozed=1` selects snoozed attention |
| `view=actions` | `items`, `nextCursor` | `before` |
| `view=recent` | `items` containing guest ID, name, update time, and follow state | Bounded recent list, not a complete thread directory |
| `view=configuration` | Accessible teams and people, routing, readiness indicators | Not paginated |
| `view=events&after={sequence}` | `events`, `cursor` | Numeric event cursor; see below |

Thread messages include `id`, `guestId`, nullable `stayId` and `parentId`, `audience`, `actorId`, `body`, `version`, `mentions`, optional guest/room `references`, reactions, and timestamps. `audience` is either `{ "type": "staff" }` or `{ "type": "team", "teamId": "team-example" }`; it is not a guest-delivery channel. Stay IDs are validated against the guest's canonical reservations.

Message, Action, and Inbox pages scan up to 100 records before visibility filtering. A short or empty page can still have a next cursor. Follow the returned cursor rather than inferring completion from array length. Thread pagination covers messages; associated Actions, runs, and legacy context are bounded projections, not a complete export.

## Event polling [#event-polling]

The implemented listener is a JSON polling endpoint, **not** a long-lived connection:

```http
GET /api/v1/orgs/hotel-example/messaging?scope=venue-example&view=events&after=0
```

Illustrative response (identifiers are fictional):

```json
{
  "data": {
    "events": [
      {
        "id": "receipt-example",
        "type": "finish",
        "resourceId": "hxp-action:example",
        "actorId": "user-example",
        "createdAt": "2026-09-19T17:00:00.000Z",
        "sequence": 42
      }
    ],
    "cursor": 42
  }
}
```

`after` must be a nonnegative safe integer. The service scans at most 100 events per request and filters by current resource, actor, team audience, and guest access. Event types are internal command/runtime names, such as `comment`, `edit`, `claim`, `finish`, and `handoff`; they are not a separately versioned public event taxonomy.

For an HXP-owned client:

1. Keep a cursor for each actor, organization, and scope. Start with `after=0` when no checkpoint exists.
2. Process visible events and refresh the relevant authorized thread, Inbox, or Action snapshot. Events contain identifiers and metadata, not message bodies or a complete after-image.
3. Persist the returned `cursor` after processing. Use it even when `events` is empty: the cursor advances across records the actor cannot see.
4. Deduplicate by event `id`. Drain advancing pages with a bounded request budget, then wait before polling again. Retry transient failures with backoff; stop and clear protected cached data when access is denied.
5. Periodically reconcile the current authorized snapshots. The feed has no published retention, replay SLA, or external delivery guarantee and is not a substitute for an export or audit archive.

HXP's current UI usually refreshes snapshots every 15 seconds, or every 2 seconds while an AI run is working, and pauses background refetching. These are UI choices, not an external polling SLA.

## Following is not an external subscription [#following-is-not-an-external-subscription]

`POST /api/v1/orgs/{orgId}/collaboration?scope={scopeId}` accepts this internal command with an `Idempotency-Key`:

```json
{
  "type": "subscribe",
  "guestId": "guest-example",
  "audience": { "type": "staff" },
  "active": true
}
```

This records the operator's followed thread for HXP attention. It does not register a callback URL. The matching read is `GET .../collaboration?scope={scopeId}&view=subscription&guest={guestId}` (add `team={teamId}` for a team audience).

There is currently no public webhook-registration API, SSE stream, WebSocket endpoint, MCP push subscription, or public event replay service. The internal collaboration worker poll route is a scheduler endpoint, not an integration listener.

## Writing a comment [#writing-a-comment]

The internal operator client posts commands to the same `/messaging?scope=...` path with JSON and a stable `Idempotency-Key`:

```json
{
  "type": "comment",
  "guestId": "guest-example",
  "stayId": null,
  "audience": { "type": "team", "teamId": "team-example" },
  "parentId": null,
  "body": "Please prepare the quiet room before arrival.",
  "sensitive": false,
  "mentions": [{ "type": "person", "id": "user-example" }]
}
```

The body is 1–6,000 characters; mentions are structured person/team IDs (maximum 20), not inferred authorization from `@` text. Guest/room references also use validated structured IDs. A successful write returns `{ "result": { "id": "...", "kind": "message", "receiptId": "..." } }`.

## Slack and SMS are specific integrations [#slack-and-sms-are-specific-integrations]

`/api/collaboration/slack/{installationId}` accepts signed Slack callbacks for a configured installation. The current handler responds to explicit app mentions, performs identity-link proof, and can start a bounded consultation for a verified linked operator. It does not import every channel message or expose general thread history. Replies direct the user to authenticated HXP; guest results remain behind HXP access.

`/api/collaboration/twilio/{installationId}` receives signed SMS delivery callbacks. Guest sending requires a ready connection, recorded consent, and approval bound to the exact effect. This callback is not an inbound guest-chat API. Other channel adapters and arbitrary third-party webhook destinations are not implied by these two implementations.
