Sessions API
Server-side conversation state under /sessions — creation, message streaming, history, summarisation, and the JWT-only guard.
- Version: 0.4
- Role: admin_user, normal_user
- Type: reference
A session is conversation state CID222 keeps for you: message history, cumulative token usage and an automatically summarised context sent to the model. You send one message at a time and CID222 supplies the history.
Warning
Every /sessions route is guarded by JWT validation alone. A gateway API key (cid_key_…)
returns 401 here, however it is presented. Use a token from POST /auth/login.
Endpoints
| Method | Path | Returns | Description |
|---|---|---|---|
| POST | /sessions | JSON | Create an empty session |
| GET | /sessions | JSON | List the tenant's chat sessions |
| GET | /sessions/:id | JSON | One session with its full history |
| PATCH | /sessions/:id | JSON | Rename a session |
| POST | /sessions/:id/messages | SSE | Send a message and stream the reply |
| DELETE | /sessions/:id | JSON | Delete a session |
POST /sessions and POST /sessions/:id/messages are writes and are refused for the auditor
role with 403 and ROLE_NOT_FOR_CHAT. Reads and deletes are scoped to the caller's own tenant.
Create a session
POST /sessions
| Field | Type | Required | Notes |
|---|---|---|---|
session_name | string | No | Label. Defaults to Chat Session - <local timestamp> |
user_id | string | No | Your own end-user identifier, stored for attribution |
The model and provider are chosen per message, not at creation time.
There is no updated_at. Recency is carried by last_used_at.
Send a message
POST /sessions/:id/messages returns text/event-stream.
| Field | Type | Required | Notes |
|---|---|---|---|
content | string | Yes | The user's message text |
model | string | Yes | Model for this turn |
provider | string | No | Disambiguates a model name offered by two providers |
temperature | number | No | 0 to 2 |
max_tokens | number | No | 1 or greater |
top_p | number | No | 0 to 1 |
imageBase64 | string | No | Base64 image for a vision model, redacted before the model sees it |
imageAnalysisSummary | object | No | Result of a prior image analysis, to skip re-filtering |
documentAnalysisSummary | object | No | Result of a prior document analysis, to skip re-filtering |
The stream
The contract matches POST /chat/completions — buffered, with the whole
reply delivered in one filtered-response event followed by data: [DONE] — with two
differences.
user_message_processed is forwarded here. The session path passes this control event through
so a UI can show what was masked in the prompt before the model saw it:
The pre-filter rejection carries a different shape. When the session's own input filter
rejects the message before the chat service is called, the event has no error field:
A rejection raised further down, inside the chat service, uses the
{"error":…,"type":"content_rejected","entities":[…]} shape documented on the Chat API page.
Handle both: match on type === "content_rejected" rather than on the presence of error.
Everything else — user_locked, security_warning, token_usage, output_content_rejected,
output_content_warning, [DONE] — behaves as on /chat/completions. There is no hallucination
event.
Get one session
GET /sessions/:id returns the session with its complete context.
Each entry in context can also carry timestamp, content_hash, had_detections,
detection_summary, filter_duration_ms, llm_duration_ms, is_rejected, rejection_reason
and imageBase64.
The response type also declares context_window_usage, but the session routes do not populate it.
Do not depend on it being present.
List sessions
GET /sessions returns every chat session belonging to the authenticated tenant, ordered by
last_used_at descending.
Note
This endpoint accepts no query parameters and does not paginate. page and limit are for admin
list endpoints; here they are ignored.
List rows deliberately omit history — a session can hold megabytes of base64 images. Each row
returns context as an empty array plus a message_count:
Only sessions of type chat are listed. Sessions created implicitly for image scans and for sessionless API traffic stay out of the list and appear under detections instead.
Rename a session
PATCH /sessions/:id takes session_name, maximum 100 characters, and returns the updated
session.
Delete a session
DELETE /sessions/:id removes the session. Related detection records are removed with it by
cascade.
Context management
- Full history is stored in
contextand returned byGET /sessions/:id. - The model context is separate. CID222 keeps a second, summarised context and sends that to the provider.
- Summarisation is threshold-driven, not model-driven. When the summarised context reaches
context_summarization_threshold_tokens— default4000— CID222 summarises the older messages and records the event insummarization_history. The trigger is that configured token count, not the model's context window. Setcontext_summarization_enabledtofalseto turn it off. - Token usage accumulates per session in
token_usage.total_tokensandtoken_usage.total_cost. - Hallucination warnings land on the session. The background retrieval-grounding check writes
has_hallucination_warningand appends tohallucination_warnings. It never appears on the stream.
Errors
| Status | Cause |
|---|---|
| 400 | Body failed validation, for example a session_name over 100 characters |
| 401 | Missing or invalid JWT — including a gateway API key, which is never accepted here |
| 403 | ROLE_NOT_FOR_CHAT for auditor on a write, READ_ONLY_ROLE for viewer on any mutation |
| 404 | No session with that id belongs to the calling tenant |
Related
- Chat API — the stateless equivalent and the full SSE event list.
- Authentication — obtaining the JWT these routes need.
- API overview — base paths and error shapes across every surface.
Last updated on