CognitiveX Docs

Chat & sessions

SSE streaming chat, follow-up suggestions, session CRUD, message history, search, export, and categories under /api/chat and /api/sessions.

This page is the contract reference for the chat surface: streaming a chat turn, managing sessions, reading message history, and organizing chats into categories. The two streaming endpoints return Server-Sent Events; everything else is plain JSON.

Base URL: https://api.cognitivx.io. Chat endpoints are mounted under /api/chat; sessions and categories under /api/sessions. Every endpoint requires auth: pass Authorization: Bearer <key> (a JWT from POST /api/auth/signin, or an API key created at developers.cognitivx.io/keys) or the X-API-Key: <key> header. An optional X-Org-ID: <id> header scopes the request to an organization. All ids are UUID strings and timestamps are ISO-8601.

Sessions are owned per user. A session you do not own returns 404, never a 403, so the API never leaks whether an id exists. The history endpoint is the one exception: it returns an empty list for an unknown or unowned session.

Endpoints

MethodPathPurpose
POST/api/chat/streamStream a chat turn (SSE)
POST/api/chat/regenerateRegenerate the last assistant message (SSE)
POST/api/chat/suggestSuggest up to 3 follow-up prompts
GET/api/sessionsList sessions (keyset pagination)
POST/api/sessionsCreate a session
GET/api/sessions/{session_id}Get one session
PATCH/api/sessions/{session_id}Rename a session
DELETE/api/sessions/{session_id}Delete a session and its messages
GET/api/sessions/{session_id}/messagesGet full message history
DELETE/api/sessions/{session_id}/messages/{message_id}Delete one message
GET/api/sessions/searchSearch message content across sessions
GET/api/sessions/exportExport all sessions as JSON or Markdown
PUT/api/sessions/{session_id}/moveMove a session to a category
PUT/api/sessions/{session_id}/pinToggle pinned
PUT/api/sessions/{session_id}/archiveToggle archived
POST/api/sessions/{session_id}/promote-to-circleConvert a session into a Circle
POST/api/sessions/categoriesCreate a category
GET/api/sessions/categoriesList categories
PATCH/api/sessions/categories/{category_id}Update a category
DELETE/api/sessions/categories/{category_id}Delete a category
PUT/api/sessions/categories/reorderReorder categories

Error responses are { "detail": "<message>" } with a 4xx/5xx status, except that once a stream has started (HTTP 200), failures are delivered in-band as SSE events rather than HTTP errors. See Streaming errors.

The TypeScript SDK (@cognitivx/sdk) does not wrap the streaming endpoints. There is no chat namespace and no client class. Call /api/chat/stream and /api/chat/regenerate over raw HTTP and parse the SSE stream yourself, as shown below. The JSON endpoints on this page can be called with apiClient or plain fetch.


Stream a chat turn

Send one user message in a session and stream iCog's reply token by token over Server-Sent Events. The server recalls relevant memories, streams the reply, persists both the user and assistant messages, and (in the background) extracts new memories and auto-titles new sessions.

POST /api/chat/stream · Authorization: Bearer <key> or X-API-Key · Optional X-Org-ID.

Request body (ChatRequest):

FieldTypeRequiredDescription
messagestringyesThe user's message text.
session_idstring (UUID)yesTarget session. Must be owned by the caller.
providerstringnoLLM provider hint. Default "openrouter". Advisory only: iCog routes the actual model internally by message complexity and budget.
file_idsstring[]noIds of previously uploaded files to attach. Default [].
content_blocksobject[]noMultimodal blocks. Each: { type: string (required), text?: string, file_id?: string, filename?: string }. Default [].
toolsstring[]noNames of connector tools to expose to the model this turn. Default [].
url_snapshot_hashstring | nullnoHash of a captured URL snapshot to analyze against memory.
deepbooleannoRequest deep multi-hop recall. Default false.
depth"quick" | "deep" | "sage" | nullnoRecall/answer depth tier. Silently clamped to the caller's plan limit.
existing_reflex_idstring | nullnoWhen set, enters reflex edit mode for that reflex (must be owned, else 403).
geo_latnumber | nullnoCaller latitude for location-aware answers.
geo_lonnumber | nullnoCaller longitude.
curl -N https://api.cognitivx.io/api/chat/stream \
  -H "Authorization: Bearer $COGNITIVX_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "message": "What did we decide about the auth migration?",
    "session_id": "5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d"
  }'

The SDK does not stream chat. Call the endpoint with fetch and parse the line-delimited SSE envelopes yourself. Concatenate only the data of type: "token" events into your UI.

const res = await fetch('https://api.cognitivx.io/api/chat/stream', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.COGNITIVX_API_KEY}`,
    'Content-Type': 'application/json',
    Accept: 'text/event-stream',
  },
  body: JSON.stringify({
    message: 'What did we decide about the auth migration?',
    session_id: '5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d',
  }),
});

const reader = res.body!.getReader();
const decoder = new TextDecoder();
let buffer = '';
let reply = '';

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  buffer += decoder.decode(value, { stream: true });

  // Events are separated by a blank line; each line starts with "data: ".
  const events = buffer.split('\n\n');
  buffer = events.pop() ?? '';

  for (const event of events) {
    const line = event.split('\n').find((l) => l.startsWith('data: '));
    if (!line) continue;
    const evt = JSON.parse(line.slice(6)); // { type, data }
    if (evt.type === 'token') reply += evt.data;
    if (evt.type === 'done') console.log('message_id:', evt.message_id);
  }
}

Response

Content-Type: text/event-stream. Each event is one line, data: <json>\n\n, where <json> is an envelope { "type": <string>, "data": <any> }. A typical ordered sequence:

data: {"type": "thinking", "data": true}

data: {"type": "recall.start", "data": {"recall_id": "a1b2c3d4", "mode": "deep", "credit_cost": 10, "expected_latency_ms": 2500}}

data: {"type": "memory_chain", "data": {"kind": "search", "query": "auth migration", "hits": 3, "total_unique": 7}}

data: {"type": "recall.complete", "data": {"recall_id": "a1b2c3d4", "actual_latency_ms": 2210, "result_count": 12}}

data: {"type": "token", "data": "You "}

data: {"type": "token", "data": "decided "}

data: {"type": "metadata", "data": {"input_tokens": 1840, "output_tokens": 96, "model": "openai/gpt-oss-120b", "provider": "openrouter"}}

data: {"type": "confidence", "data": {"memory_count": 12, "scored_count": 5, "mean_confidence": 0.83, "min_confidence": 0.41, "low_confidence_ratio": 0.2}}

data: {"type": "done", "data": true, "message_id": "7c1e9a02-3b4d-4f6a-8c2e-9d0b1a2c3e4f"}

done.message_id is the persisted assistant message UUID. It is null for short-circuit turns (for example reflex-creation cards or reflex edit mode).

Behind Cloudflare the server sets X-Accel-Buffering: no and Cache-Control: no-cache so events flush immediately. Do not buffer the whole body, and use SSE (an EventSource-style reader), not WebSockets. The 200 response also carries quota headers (used / limit / remaining).

Event types

The type field on the envelope can be any of the following. The only one you concatenate for prose is token; treat the rest as structured side-channel data and render or ignore them as you see fit.

Eventdata shape / meaning
thinkingboolean. The model is working.
tokenstring delta. Append these for the reply text.
metadataPer-LLM-round usage: input_tokens, output_tokens, model, provider. Adds cost_usd only on the PAYG tier.
recall.start / recall.completeRecall lifecycle, with recall_id and latency.
memory_chain, deep_plan, deep_search, deep_reflect, deep_synthesizeRecall progress, including deep multi-hop steps.
confidenceAggregate confidence over the recalled memories.
model_downgrade, credit_estimateRouting/budget notices.
web_search, places, imageTool/result surfaces.
ui_block, text_block, reasoningRich content blocks (for example charts or tables from a spreadsheet, or reflex-creation cards).
tool_call_start, tool_call_result, tool_confirmConnector tool loop.
url_suggestions, url_auto_learned, url_resurface, research_intent, insight_cardProactive and research surfaces.
error, credits_exhaustedIn-band failures (see below).
doneTerminal event. Always sent. Carries message_id.

Errors

Before the stream starts, normal HTTP errors apply:

  • 401 — missing or invalid key.
  • 403 — existing_reflex_id belongs to another user (detail: "forbidden").
  • 404 — session_id not owned by the caller ("Session not found").
  • 422 — message or session_id missing or malformed.
  • 503 — "LLM Router not initialized".

Once the stream has started (HTTP 200), failures are delivered in-band as events, not as HTTP errors:

data: {"type": "error", "data": "<message>"}

data: {"type": "credits_exhausted", "data": {"current_tier": "free", "cap_reset_at": "2026-07-01T00:00:00Z", "upgrade": {...}}}

credits_exhausted fires when monthly recall credits run out and includes the current tier, the cap reset time, and upgrade/top-up options. In both cases you still receive a terminal done event, so always wait for it.


Regenerate the last assistant message

Delete the last assistant message in a session and re-stream a fresh reply. Same SSE contract as /api/chat/stream. If message is empty, the server reuses the last user message in the session as the prompt. The trailing assistant row is only deleted when the last message's role is actually assistant.

POST /api/chat/regenerate · Authorization: Bearer <key> or X-API-Key · Optional X-Org-ID.

Body is the same ChatRequest as /api/chat/stream. message may be "" to regenerate against the existing last user message; session_id is still required.

curl -N https://api.cognitivx.io/api/chat/regenerate \
  -H "Authorization: Bearer $COGNITIVX_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{"message": "", "session_id": "5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d"}'

The response is an identical SSE stream, ending with a done event whose message_id is the new assistant message UUID.

Errors: same as /api/chat/stream (401, 404 "Session not found", 422, 503), plus in-band error / credits_exhausted events once streaming begins.


Suggest follow-up prompts

Return up to 3 short suggested next prompts based on the last assistant message. Non-streaming JSON.

POST /api/chat/suggest · Authorization: Bearer <key> or X-API-Key · Optional X-Org-ID.

Request body (SuggestRequest):

FieldTypeRequiredDescription
last_messagestringyesThe last assistant message text. Truncated server-side to 1000 chars.
session_idstringyesThe session the suggestions are for.
curl https://api.cognitivx.io/api/chat/suggest \
  -H "Authorization: Bearer $COGNITIVX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "last_message": "The auth migration moved sessions to JWT...",
    "session_id": "5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d"
  }'
{
  "suggestions": [
    "Show me the migration diff",
    "What broke for existing users?",
    "How do we roll back?"
  ]
}

Each suggestion is capped under 40 chars and the list is trimmed to at most 3 strings.

Errors: 401 invalid key. 422 missing last_message/session_id. 503 "LLM Router not initialized". On any generation or parse failure the endpoint returns 200 with { "suggestions": [] }, so it never errors mid-suggest.


List sessions

List the caller's sessions ordered by (updated_at DESC, id DESC) with cursor pagination. When q is set, all title matches are returned in one shot (pagination is bypassed).

GET /api/sessions · Authorization: Bearer <key> or X-API-Key · Optional X-Org-ID.

Query paramTypeRequiredDescription
qstring | nullnoFilters session titles (ILIKE). When set, pagination is bypassed.
include_archivedbooleannoInclude archived sessions. Default false.
limitintegernoPage size, 1–200. Default 50.
cursorstring | nullnoOpaque cursor from a prior next_cursor. Omit for the first page.
curl "https://api.cognitivx.io/api/sessions?limit=20" \
  -H "Authorization: Bearer $COGNITIVX_API_KEY"
{
  "sessions": [
    {
      "id": "5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d",
      "title": "Auth migration plan",
      "provider": "openrouter",
      "model": "openai/gpt-oss-120b",
      "created_at": "2026-06-10T14:02:11Z",
      "updated_at": "2026-06-15T09:31:44Z",
      "message_count": 8,
      "last_message_preview": "You decided to move sessions to JWT...",
      "category_id": null,
      "category_name": null,
      "is_pinned": false,
      "is_archived": false,
      "initiated_by": null,
      "unread": false
    }
  ],
  "total": 1,
  "next_cursor": "2026-06-15T09:31:44+00:00|5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d",
  "has_more": true
}

total is the count of the current page, not the full collection. To page, pass the returned next_cursor back as cursor. next_cursor is null when there are no more pages, and is always null when q is set (search is single-shot).

Errors: 401 invalid key. 400 "Invalid cursor" when the cursor is malformed. 422 when limit is outside 1–200.


Create session

Create an empty chat session. Use the returned id as session_id for /api/chat/stream.

POST /api/sessions · Authorization: Bearer <key> or X-API-Key · Optional X-Org-ID.

FieldTypeRequiredDescription
titlestringnoSession title. Default "New Chat".
curl https://api.cognitivx.io/api/sessions \
  -H "Authorization: Bearer $COGNITIVX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title": "Auth migration plan"}'
{
  "id": "5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d",
  "title": "Auth migration plan",
  "provider": null,
  "model": null,
  "created_at": "2026-06-16T10:00:00Z",
  "updated_at": "2026-06-16T10:00:00Z",
  "message_count": 0,
  "last_message_preview": null
}

The title is optional and may be overwritten: the chat pipeline auto-titles a session from its first exchange.

Errors: 401 invalid key. 422 malformed body.


Get session

Fetch a single session with its current message_count and last_message_preview.

GET /api/sessions/{session_id} · Authorization: Bearer <key> or X-API-Key · Optional X-Org-ID.

Path paramTypeRequiredDescription
session_idstring (UUID)yesThe session to fetch.
curl https://api.cognitivx.io/api/sessions/5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d \
  -H "Authorization: Bearer $COGNITIVX_API_KEY"
{
  "id": "5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d",
  "title": "Auth migration plan",
  "provider": "openrouter",
  "model": "openai/gpt-oss-120b",
  "created_at": "2026-06-10T14:02:11Z",
  "updated_at": "2026-06-15T09:31:44Z",
  "message_count": 8,
  "last_message_preview": "You decided to move sessions to JWT..."
}

Errors: 401 invalid key. 404 "Session not found" (also returned for sessions owned by another user).


Rename session

Update a session's title.

PATCH /api/sessions/{session_id} · Authorization: Bearer <key> or X-API-Key · Optional X-Org-ID.

FieldTypeRequiredDescription
titlestringyesNew title.
curl -X PATCH https://api.cognitivx.io/api/sessions/5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d \
  -H "Authorization: Bearer $COGNITIVX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title": "Auth migration (final)"}'
{
  "id": "5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d",
  "title": "Auth migration (final)",
  "provider": "openrouter",
  "model": "openai/gpt-oss-120b",
  "created_at": "2026-06-10T14:02:11Z",
  "updated_at": "2026-06-16T10:05:00Z",
  "message_count": 8,
  "last_message_preview": "You decided to move sessions to JWT..."
}

Errors: 401 invalid key. 404 "Session not found". 422 missing title.


Delete session

Delete a session and all of its messages.

DELETE /api/sessions/{session_id} · Authorization: Bearer <key> or X-API-Key · Optional X-Org-ID.

Path paramTypeRequiredDescription
session_idstring (UUID)yesThe session to delete.
curl -X DELETE https://api.cognitivx.io/api/sessions/5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d \
  -H "Authorization: Bearer $COGNITIVX_API_KEY"
{ "message": "Session deleted" }

Errors: 401 invalid key. 404 "Session not found".


Get session messages

Return the full ordered message history for a session, including each message's recalled memories, web sources, UI blocks, and tool invocations.

GET /api/sessions/{session_id}/messages · Authorization: Bearer <key> or X-API-Key · Optional X-Org-ID.

Path paramTypeRequiredDescription
session_idstring (UUID)yesThe session whose messages to fetch.
curl https://api.cognitivx.io/api/sessions/5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d/messages \
  -H "Authorization: Bearer $COGNITIVX_API_KEY"
{
  "messages": [
    {
      "id": "9d0b1a2c-3e4f-4a5b-8c6d-7e8f9a0b1c2d",
      "session_id": "5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d",
      "role": "user",
      "content": "What did we decide about the auth migration?",
      "provider": null,
      "model": null,
      "created_at": "2026-06-15T09:31:40Z",
      "recalled_memories": null,
      "web_sources": null,
      "ui_blocks": null,
      "tool_invocations": null
    },
    {
      "id": "7c1e9a02-3b4d-4f6a-8c2e-9d0b1a2c3e4f",
      "session_id": "5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d",
      "role": "assistant",
      "content": "You decided to move sessions to JWT...",
      "provider": "openrouter",
      "model": "openai/gpt-oss-120b",
      "created_at": "2026-06-15T09:31:44Z",
      "recalled_memories": { "count": 12 },
      "web_sources": [],
      "ui_blocks": [],
      "tool_invocations": []
    }
  ]
}

recalled_memories is an object (or null); web_sources, ui_blocks, and tool_invocations are arrays (or null).

Errors: 401 invalid key. An unknown or unowned session returns { "messages": [] } rather than 404.


Delete message

Delete a single message by id.

DELETE /api/sessions/{session_id}/messages/{message_id} · Authorization: Bearer <key> or X-API-Key · Optional X-Org-ID.

Path paramTypeRequiredDescription
session_idstring (UUID)yesKept for REST consistency; not used for lookup.
message_idstring (UUID)yesThe message to delete.
curl -X DELETE https://api.cognitivx.io/api/sessions/5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d/messages/7c1e9a02-3b4d-4f6a-8c2e-9d0b1a2c3e4f \
  -H "Authorization: Bearer $COGNITIVX_API_KEY"
{ "message": "Message deleted" }

Errors: 401 invalid key. 404 "Message not found".


Search messages

Search message content across all of the caller's sessions.

GET /api/sessions/search · Authorization: Bearer <key> or X-API-Key · Optional X-Org-ID.

Query paramTypeRequiredDescription
qstringyesSearch query. Queries shorter than 2 chars return an empty result.
curl "https://api.cognitivx.io/api/sessions/search?q=auth%20migration" \
  -H "Authorization: Bearer $COGNITIVX_API_KEY"
{
  "results": [
    {
      "session_id": "5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d",
      "message_id": "7c1e9a02-3b4d-4f6a-8c2e-9d0b1a2c3e4f",
      "content": "...auth migration...",
      "role": "assistant"
    }
  ]
}

The result shape is a loose dict, not a typed model.

Errors: 401 invalid key. Returns { "results": [] } when q is empty or shorter than 2 characters (no error).


Export sessions

Download all of the caller's sessions and messages as a single JSON or Markdown file. Both forms set Content-Disposition: attachment.

GET /api/sessions/export · Authorization: Bearer <key> or X-API-Key · Optional X-Org-ID.

Query paramTypeRequiredDescription
formatstringno"json" (default) or "markdown". Any value other than "markdown" yields JSON.
curl "https://api.cognitivx.io/api/sessions/export?format=markdown" \
  -H "Authorization: Bearer $COGNITIVX_API_KEY" -o icog-export.md

JSON form:

{
  "exported_at": "2026-06-16T10:00:00Z",
  "user_email": "[email protected]",
  "sessions": [
    {
      "id": "5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d",
      "title": "Auth migration plan",
      "created_at": "2026-06-10T14:02:11Z",
      "updated_at": "2026-06-15T09:31:44Z",
      "messages": [
        { "role": "user", "content": "...", "created_at": "..." }
      ]
    }
  ]
}

The Markdown form returns text/markdown.

Errors: 401 invalid key.


Move session to category

Move a session into a category, or to Unsorted when category_id is null.

PUT /api/sessions/{session_id}/move · Authorization: Bearer <key> or X-API-Key · Optional X-Org-ID.

FieldTypeRequiredDescription
category_idstring | nullyesTarget category id, or null for Unsorted. Send null explicitly to unsort.
curl -X PUT https://api.cognitivx.io/api/sessions/5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d/move \
  -H "Authorization: Bearer $COGNITIVX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"category_id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d"}'
{
  "id": "5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d",
  "title": "Auth migration plan",
  "created_at": "2026-06-10T14:02:11Z",
  "updated_at": "2026-06-16T10:10:00Z",
  "message_count": 8,
  "category_id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
  "category_name": null,
  "is_pinned": false,
  "is_archived": false
}

category_name is not populated by the move response.

Errors: 401 invalid key. 404 "Session or category not found". 422 when the category_id key is missing (send null explicitly to unsort).


Toggle session pin

Toggle the pinned state. Pinning also unarchives; unpinning leaves the archive state unchanged.

PUT /api/sessions/{session_id}/pin · Authorization: Bearer <key> or X-API-Key · Optional X-Org-ID. No body.

curl -X PUT https://api.cognitivx.io/api/sessions/5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d/pin \
  -H "Authorization: Bearer $COGNITIVX_API_KEY"
{
  "id": "5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d",
  "title": "Auth migration plan",
  "created_at": "2026-06-10T14:02:11Z",
  "updated_at": "2026-06-16T10:11:00Z",
  "message_count": 8,
  "is_pinned": true,
  "is_archived": false,
  "category_id": null,
  "category_name": null
}

Errors: 401 invalid key. 404 "Session not found".


Toggle session archive

Toggle the archived state. Archiving also unpins; unarchiving leaves the pin state unchanged.

PUT /api/sessions/{session_id}/archive · Authorization: Bearer <key> or X-API-Key · Optional X-Org-ID. No body.

curl -X PUT https://api.cognitivx.io/api/sessions/5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d/archive \
  -H "Authorization: Bearer $COGNITIVX_API_KEY"
{
  "id": "5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d",
  "title": "Auth migration plan",
  "created_at": "2026-06-10T14:02:11Z",
  "updated_at": "2026-06-16T10:12:00Z",
  "message_count": 8,
  "is_pinned": false,
  "is_archived": true,
  "category_id": null,
  "category_name": null
}

Errors: 401 invalid key. 404 "Session not found".


Promote session to Circle

Convert a private chat session into a (private) Circle, copying all messages into it with the caller as owner. The session title is truncated to 100 chars for the Circle's name and subject.

POST /api/sessions/{session_id}/promote-to-circle · Authorization: Bearer <key> or X-API-Key · Optional X-Org-ID. No body.

curl -X POST https://api.cognitivx.io/api/sessions/5f3c9b2a-1d4e-4a7b-9c8d-2e1f0a3b4c5d/promote-to-circle \
  -H "Authorization: Bearer $COGNITIVX_API_KEY"
{
  "id": "c0ffee00-1111-4222-8333-444455556666",
  "name": "Auth migration plan",
  "subject": "Auth migration plan",
  "description": null,
  "visibility": "private",
  "avatar_url": null,
  "member_count": 1,
  "role": "owner",
  "budget_tokens_monthly": null,
  "budget_used_tokens": 0,
  "created_at": "2026-06-16T10:12:00Z",
  "updated_at": "2026-06-16T10:12:00Z"
}

Errors: 401 invalid key. 404 "Session not found".


Categories

Categories are folders for organizing sessions. The category routes are declared before the /{session_id} and /{category_id} routes so that /api/sessions/categories and /api/sessions/categories/reorder are never shadowed by an id path.

Create category

POST /api/sessions/categories · Authorization: Bearer <key> or X-API-Key · Optional X-Org-ID.

FieldTypeRequiredDescription
namestringyesCategory name.
colorstringnoHex color. Default "#8b5cf6".
iconstringnoIcon name. Default "folder".
curl https://api.cognitivx.io/api/sessions/categories \
  -H "Authorization: Bearer $COGNITIVX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Engineering", "color": "#7c3aed", "icon": "code"}'
{
  "id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
  "name": "Engineering",
  "position": 0,
  "color": "#7c3aed",
  "icon": "code",
  "created_at": "2026-06-16T10:15:00Z",
  "updated_at": "2026-06-16T10:15:00Z"
}

Errors: 401 invalid key. 422 missing name.

List categories

GET /api/sessions/categories · Authorization: Bearer <key> or X-API-Key · Optional X-Org-ID. No params.

curl https://api.cognitivx.io/api/sessions/categories \
  -H "Authorization: Bearer $COGNITIVX_API_KEY"
{
  "categories": [
    {
      "id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
      "name": "Engineering",
      "position": 0,
      "color": "#7c3aed",
      "icon": "code",
      "created_at": "2026-06-16T10:15:00Z",
      "updated_at": "2026-06-16T10:15:00Z"
    }
  ]
}

Categories are returned in position order.

Errors: 401 invalid key.

Update category

Rename a category or change its color/icon. All fields are optional; omitted or empty fields keep their current value.

PATCH /api/sessions/categories/{category_id} · Authorization: Bearer <key> or X-API-Key · Optional X-Org-ID.

FieldTypeRequiredDescription
namestring | nullnoNew name. Current name kept if omitted/empty.
colorstring | nullnoNew hex color.
iconstring | nullnoNew icon name.
curl -X PATCH https://api.cognitivx.io/api/sessions/categories/a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d \
  -H "Authorization: Bearer $COGNITIVX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Eng & Infra"}'
{
  "id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
  "name": "Eng & Infra",
  "position": 0,
  "color": "#7c3aed",
  "icon": "code",
  "created_at": "2026-06-16T10:15:00Z",
  "updated_at": "2026-06-16T10:20:00Z"
}

Errors: 401 invalid key. 404 "Category not found".

Delete category

Delete a category. Its sessions move to Unsorted.

DELETE /api/sessions/categories/{category_id} · Authorization: Bearer <key> or X-API-Key · Optional X-Org-ID.

curl -X DELETE https://api.cognitivx.io/api/sessions/categories/a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d \
  -H "Authorization: Bearer $COGNITIVX_API_KEY"
{ "message": "Category deleted" }

Errors: 401 invalid key. 404 "Category not found".

Reorder categories

Set the category display order from an ordered list of ids.

PUT /api/sessions/categories/reorder · Authorization: Bearer <key> or X-API-Key · Optional X-Org-ID.

FieldTypeRequiredDescription
category_idsstring[]yesCategory ids in the desired order.
curl -X PUT https://api.cognitivx.io/api/sessions/categories/reorder \
  -H "Authorization: Bearer $COGNITIVX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"category_ids": ["a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d", "b2c3d4e5-6f7a-4b8c-9d0e-1f2a3b4c5d6e"]}'
{ "message": "Categories reordered" }

Errors: 401 invalid key. 422 missing category_ids.