Chat
List, send, rename, and delete workspace Command Center threads.
Chat HTTP persists threads and user/assistant messages. Each successful send also enqueues a
Confluye Command job (legacy module name fluxus-command). This is not an SSE/token stream: the
handler returns after enqueue (and any in-process dispatch). Poll the job for progress.
| Prefix | Auth | Envelope |
|---|---|---|
/api/chat | Signed-in session | Bare JSON { error } / resource objects |
/api/v1/chat | Bearer API key | Same bare JSON (not api-contracts.v1) |
Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /api/chat | List threads (?workspaceId=) |
| POST | /api/chat | Send / create thread (201) |
| PATCH | /api/chat/{id} | Rename ({ title }) |
| DELETE | /api/chat/{id} | Delete ({ deleted: true }) |
| GET | /api/v1/chat | List threads in the key workspace |
| POST | /api/v1/chat | Send (201); workspace key |
| PATCH | /api/v1/chat/{id} | Rename |
| DELETE | /api/v1/chat/{id} | Delete |
There is no GET /api/chat/{id} and no message-level edit/delete route.
Auth and roles
Session. workspaceId query/body defaults to the session workspace. Another workspace is
allowed only if the user is a member. Otherwise 403:
- List / rename / delete:
Cannot access chat threads for another workspace. - Send:
Cannot create chat threads for another workspace.
Continuing a threadId that belongs to a different workspace is also 403 (create message).
There is no extra Viewer/Member gate on these routes beyond membership.
v1. Missing/invalid bearer: 401 Valid bearer API key is required. GET/PATCH/DELETE
accept any valid key and scope to apiKey.workspaceId. POST requires scope === "workspace"
(403 A workspace API key is required.). Foreign threadId: 404 Chat thread not found.
Foreign workflowId: 403 API key cannot access this workflow. Missing workflow: 404.
Send
{
"message": "show docs and knowledge base status",
"threadId": "optional-existing-thread",
"workflowId": "optional-scope",
"workspaceId": "session-only",
"assistantContext": "optional extra planner context",
"aiProvider": "session-only",
"aiModel": "session-only",
"attachmentFileIds": ["file-uuid"]
}
| Field | Rules |
|---|---|
message | Required after trim. Empty: 400 Message is required |
threadId | Optional. Missing thread in workspace: v1 404; session may create a new thread if the id is unknown and not foreign |
workflowId | Optional; stored on a new thread |
workspaceId | Session only. v1 ignores body workspace and uses the key |
assistantContext | Planner input; the stored user message stays the raw message |
aiProvider/aiModel | Session Command/chat only; v1 POST does not forward these |
attachmentFileIds | Optional. Array of non-empty strings, max 10. Else 400 attachmentFileIds must contain at most 10 valid file IDs. |
201 body (same shape as sendWorkspaceChatMessage):
| Field | Notes |
|---|---|
thread | Full ChatThreadSummary including messages |
assistantMessage | Latest assistant line for this job, if the worker already appended it |
commandJob | Public job (id, status, traces, confirmation, progress, …) |
queued | true when job status === "queued" |
replayed | true only for an internal commandJobId reload, not HTTP replay |
A first send typically yields two messages (user, then assistant once the job completes in
process). If the job stays queued, assistantMessage may be absent until you poll.
Attachments must exist in the workspace (404 WorkspaceFileNotFoundError message) and be
ready (409 ChatWorkspaceFileNotReadyError message). Failed bind rolls back the user
message and job attachments.
Thread object
| Field | Notes |
|---|---|
id | Thread id |
workspaceId | Workspace |
workflowId | Optional scope |
title | Auto from first message; PATCH replaces |
createdAt | ISO-8601 |
updatedAt | ISO-8601 |
messages | See below |
Message: id, threadId, role (user | assistant), content, optional actions,
citations, ragMode (ai | unavailable | extractive), fluxusCommandPlan,
fluxusCommandJob, attachments, createdAt. The fluxus* field names are compatibility
identifiers on the stored message.
PATCH { "title": "…" } — blank title: 400 Chat title is required. Missing thread after
auth: 404 Chat thread not found.
DELETE { "deleted": true } or 404.
GET list: { threads } for that workspace. No cursor, no limit.
Errors
| HTTP | Typical body | Cause |
|---|---|---|
| 400 | Message is required / title / attachments | Validation |
| 400 | { error: { code: "idempotency_key_invalid" } } | Missing/invalid Idempotency-Key on POST |
| 401 | Valid bearer API key is required | v1 |
| 403 | Cross-workspace or non-workspace key on POST | Authz |
| 404 | Thread / workflow / file | Missing in scope |
| 409 | File not ready; idempotency mismatch | Conflict |
| 500 | Chat request failed. or thrown message | Unclassified send |
Gaps
- List is unpaginated and includes full message arrays.
- No dedicated get-thread route; clients list or keep the send payload.
- Session send accepts
aiProvider/aiModel; v1 send does not. - Session
threadIdthat is unknown but not foreign creates a new thread instead of404. - Confirm/cancel/retry are not on
/api/chat; use Command.
