CORTEX

Conversations

The live chat loop and the workspace it lives in: projects, threads, messages, attachments, runs, artifacts, and the approval gates that pause runs for human review.

Common responses

These responses apply across endpoints in this section unless an endpoint documents an additional response.

StatusMeaningBody
200Request succeeded.Endpoint response object.
201Resource created.Created resource object.
400Invalid request.Error envelope.
401Missing or invalid bearer token.Error envelope.
404Resource not found or not visible to the current organization.Error envelope.

Projects

List projects

Return projects the caller can access within their organization — projects they created, plus projects where they're an explicit member. Projects the caller isn't on are omitted entirely, not just hidden behind a 403. Tri-state filter on archived state: omit `isArchived` (or send `isArchived=false`) to get only active projects; send `isArchived=true` to get only archived projects. Each item contains the full project object plus list-view aggregates: `conversation_count` (threads bound to the project), `file_count` (project files with status `ready`), `member_count` (project_members rows, plus the creator if the creator has no explicit member row), `member_preview` — up to 5 `{user_id, display_name}` entries, creator first, then members ordered by when they were added — and `viewer_role` (`admin` or `member`), the calling user's own role on that project: the creator is always `admin` (even with no explicit member row, or a `member` row of their own), otherwise it's their `project_members` row's role. Aggregates are computed with a handful of batched queries over the returned page, not one query per project.

GET/v1/projects

Query parameters

NameTypeRequiredDescription
isArchivedbooleanOptionalFilters by status. `true` returns only archived projects; `false` returns only active. Omit for the default (active only). Mirrors the `isDeleted` filter on `/admin/organizations`.
Example requestbash
curl "https://api.cortex.cognit-dx.com/v1/projects?is_archived=false" \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
200 OKjson
{
  "data": [
    {
      "id": "9960c593-9a95-42a8-b26b-a50b4bd915e2",
      "organization_id": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815",
      "name": "Consulting Pipeline Command Center",
      "description": "Sales and delivery operating dashboard covering pipeline, proposal conversion, workshop bookings, and utilization.",
      "status": "active",
      "created_by": "39a69cb1-c14c-481d-85fb-fd43c8046440",
      "created_at": "2026-04-13T17:17:37.817Z",
      "updated_at": "2026-05-17T11:17:37.817Z",
      "conversation_count": 12,
      "file_count": 4,
      "member_count": 3,
      "member_preview": [
        {
          "user_id": "39a69cb1-c14c-481d-85fb-fd43c8046440",
          "display_name": "Priya Shah"
        },
        {
          "user_id": "ed089c8c-c528-4c41-951e-45c4dba58384",
          "display_name": "Marcus Lee"
        }
      ],
      "viewer_role": "admin"
    },
    {
      "id": "4ff06370-0727-4f1a-ab37-e9055e0b7a47",
      "organization_id": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815",
      "name": "Hybridx AI Demo Suite",
      "description": "AI Studio demo assets showing agents, dashboards, document intelligence, and executive reporting workflows.",
      "status": "active",
      "created_by": "ed089c8c-c528-4c41-951e-45c4dba58384",
      "created_at": "2026-03-17T17:17:37.817Z",
      "updated_at": "2026-05-16T17:17:37.817Z",
      "conversation_count": 3,
      "file_count": 0,
      "member_count": 1,
      "member_preview": [
        {
          "user_id": "ed089c8c-c528-4c41-951e-45c4dba58384",
          "display_name": "Marcus Lee"
        }
      ],
      "viewer_role": "member"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Create project

Create a new project within the caller's organization. Project names must be unique among active projects in the same organization — a 409 is returned if an active project with the same name already exists. The full project object is returned on success with HTTP 201.

POST/v1/projects

Request body

NameTypeRequiredDescription
namestringRequiredDisplay name for the project. Trimmed; must be between 1 and 255 characters. Must be unique among active projects in the organization.
descriptionstringOptionalOptional free-text description of the project. Maximum 5000 characters. Pass null to explicitly clear an existing description.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/projects \
  -X POST \
  -H "Authorization: Bearer $CORTEX_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"name":"Sales assistant"}'

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
400Request body failed validation.`{ error, code, request_id }`
201 Createdjson
{
  "id": "24d9ed5b-b683-43d5-bea4-8adc9f8dd09b",
  "organization_id": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815",
  "name": "Smoke test project (batch 5)",
  "description": "Created during the docs upgrade smoke test.",
  "status": "active",
  "created_by": "0ce6409a-3bfa-4e2f-883a-5a696b451d8b",
  "created_at": "2026-05-18T08:34:39.659Z",
  "updated_at": "2026-05-18T08:34:39.659Z"
}

Get project

Get a single project by ID. The caller must be able to access the project — its creator or an explicit member. Returns 404 if the project does not exist, belongs to a different organization, or the caller isn't on it; all three cases are indistinguishable.

GET/v1/projects/:id

Path parameters

NameTypeRequiredDescription
idstringRequiredThe id value from the endpoint path.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/projects/9f7c9d3a-1234-5678-9abc-def012345678 \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
200 OKjson
{
  "id": "9960c593-9a95-42a8-b26b-a50b4bd915e2",
  "organization_id": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815",
  "name": "Consulting Pipeline Command Center",
  "description": "Sales and delivery operating dashboard covering pipeline, proposal conversion, workshop bookings, and utilization.",
  "status": "active",
  "created_by": "39a69cb1-c14c-481d-85fb-fd43c8046440",
  "created_at": "2026-04-13T17:17:37.817Z",
  "updated_at": "2026-05-17T11:17:37.817Z"
}

Update project

Update a project's name, description, or status. All fields are optional — send only what you want to change. Renaming to a name already in use by another active project in the same organization returns 409. Only a project admin may update a project — the project's creator counts as an implicit admin. A member without the admin role gets 403; a caller who can't access the project at all (or an unknown/cross-org project id) gets 404.

PATCH/v1/projects/:id

Path parameters

NameTypeRequiredDescription
idstringRequiredThe id value from the endpoint path.

Request body

NameTypeRequiredDescription
namestringOptionalNew display name. Trimmed; 1–255 characters. Must be unique among active projects in the organization.
descriptionstringOptionalUpdated description. Pass `null` to clear. Maximum 5000 characters.
statusstringOptionalProject status. Accepted values: `active`, `archived`.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/projects/9f7c9d3a-1234-5678-9abc-def012345678 \
  -X PATCH \
  -H "Authorization: Bearer $CORTEX_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"name":"Sales assistant","description":"Created via the docs example.","status":"example"}'

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
403The caller is a project member but not an admin.`{ error, code, request_id }`
404Resource not found, or not accessible to the caller at all.`{ error, code, request_id }`
400Request body failed validation.`{ error, code, request_id }`
200 OKjson
{
  "id": "9960c593-9a95-42a8-b26b-a50b4bd915e2",
  "organization_id": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815",
  "name": "Consulting Pipeline Command Center v2",
  "description": "Expanded to cover utilization forecasting and staffing capacity planning.",
  "status": "active",
  "created_by": "39a69cb1-c14c-481d-85fb-fd43c8046440",
  "created_at": "2026-04-13T17:17:37.817Z",
  "updated_at": "2026-05-21T10:30:00.000Z"
}

Archive project

Soft-delete a project by setting its status to `archived`. The project remains queryable via `GET /projects?isArchived=true`. Same authorization as PATCH /projects/:id: only a project admin may archive (creator counts as an implicit admin). Returns 204 on success, 403 if the caller is a member but not an admin, or 404 if the project doesn't exist or isn't accessible to the caller at all.

DELETE/v1/projects/:id

Path parameters

NameTypeRequiredDescription
idstringRequiredThe id value from the endpoint path.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/projects/9f7c9d3a-1234-5678-9abc-def012345678 \
  -X DELETE \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
403The caller is a project member but not an admin.`{ error, code, request_id }`
404Resource not found, or not accessible to the caller at all.`{ error, code, request_id }`
204 No Contenttext

List project members

List the members of a project — the users who can read and reply in the project's threads. Returns a cursor-paginated array of member records, each with the user id, the member's role (`admin` or `member`), who added them, and when. The caller must be able to access the project (its creator or an explicit member); another organization's project, a nonexistent project, or a project the caller isn't on all return 404 identically.

GET/v1/projects/:id/members

Path parameters

NameTypeRequiredDescription
idstringRequiredThe project ID whose members to list.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/projects/9960c593-9a95-42a8-b26b-a50b4bd915e2/members \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
200 OKjson
{
  "data": [
    {
      "project_id": "9960c593-9a95-42a8-b26b-a50b4bd915e2",
      "user_id": "0ce6409a-3bfa-4e2f-883a-5a696b451d8b",
      "role": "admin",
      "added_by_user_id": "0ce6409a-3bfa-4e2f-883a-5a696b451d8b",
      "added_at": "2026-05-18T08:34:39.659Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Add project member

Add a user to a project. Only a project admin (or the project's creator) may add members. The member is created with the requested role, defaulting to `member`. Returns 201 with the new member record. A 409 is returned if the user is already a member of the project.

POST/v1/projects/:id/members

Path parameters

NameTypeRequiredDescription
idstringRequiredThe project ID to add the member to.

Request body

NameTypeRequiredDescription
userIdstringRequiredUUID of the user to add. Must belong to the caller's organization.
rolestringOptionalMember role. One of `admin` or `member`. Defaults to `member`.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/projects/9960c593-9a95-42a8-b26b-a50b4bd915e2/members \
  -X POST \
  -H "Authorization: Bearer $CORTEX_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"user_id":"0ce6409a-3bfa-4e2f-883a-5a696b451d8b","role":"member"}'

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
403Forbidden — only a project admin can add members.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
409User is already a member of this project.`{ error, code, request_id }`
422Request body failed validation.`{ error, code, request_id }`
201 Createdjson
{
  "project_id": "9960c593-9a95-42a8-b26b-a50b4bd915e2",
  "user_id": "0ce6409a-3bfa-4e2f-883a-5a696b451d8b",
  "role": "member",
  "added_by_user_id": "39a69cb1-c14c-481d-85fb-fd43c8046440",
  "added_at": "2026-05-18T08:34:39.659Z"
}

Update project member

Change a member's role within a project. Only a project admin may change roles. Returns the updated member record. A 404 is returned if the user is not a member of the project.

PATCH/v1/projects/:id/members/:userId

Path parameters

NameTypeRequiredDescription
idstringRequiredThe project ID that owns the member.
userIdstringRequiredUUID of the member whose role to change.

Request body

NameTypeRequiredDescription
rolestringRequiredNew member role. One of `admin` or `member`.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/projects/9960c593-9a95-42a8-b26b-a50b4bd915e2/members/0ce6409a-3bfa-4e2f-883a-5a696b451d8b \
  -X PATCH \
  -H "Authorization: Bearer $CORTEX_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"role":"admin"}'

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
403Forbidden — only a project admin can change member roles.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
422Request body failed validation.`{ error, code, request_id }`
200 OKjson
{
  "project_id": "9960c593-9a95-42a8-b26b-a50b4bd915e2",
  "user_id": "0ce6409a-3bfa-4e2f-883a-5a696b451d8b",
  "role": "admin",
  "added_by_user_id": "39a69cb1-c14c-481d-85fb-fd43c8046440",
  "added_at": "2026-05-18T08:34:39.659Z"
}

Remove project member

Remove a member from a project. A user may always remove themselves; removing another member requires project admin. Returns 204 on success. A 404 is returned if the user is not a member of the project.

DELETE/v1/projects/:id/members/:userId

Path parameters

NameTypeRequiredDescription
idstringRequiredThe project ID that owns the member.
userIdstringRequiredUUID of the member to remove.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/projects/9960c593-9a95-42a8-b26b-a50b4bd915e2/members/0ce6409a-3bfa-4e2f-883a-5a696b451d8b \
  -X DELETE \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
403Forbidden — only a project admin can remove other members.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
204 No Contenttext

Project files

Create project file upload URL

Initiate a two-step direct-to-storage upload for a project file — a document shared by every thread in the project, as opposed to a per-thread attachment. Step 1 — call this endpoint to create a pending project file record and receive a pre-signed PUT URL. Step 2 — PUT the raw file bytes directly to that URL (no Authorization header). Step 3 — call POST /project-files/:id/commit to mark the file ready, which also enqueues it for ingestion. The pre-signed URL expires in 15 minutes. Only a project member may upload (the project's creator counts as an implicit member); an org member who is not on the project gets 403.

POST/v1/projects/:id/files/upload-url

Path parameters

NameTypeRequiredDescription
idstringRequiredThe project ID this file will belong to.

Request body

NameTypeRequiredDescription
filenamestringRequiredOriginal file name including extension. Maximum 512 characters.
mimeTypestringRequiredMIME type of the file, e.g. application/pdf. Maximum 255 characters.
sizeBytesnumberRequiredFile size in bytes. Must be a positive integer.
Step 1 — request a pre-signed upload URLbash
curl https://api.cortex.cognit-dx.com/v1/projects/9960c593-9a95-42a8-b26b-a50b4bd915e2/files/upload-url \
  -X POST \
  -H "Authorization: Bearer $CORTEX_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
    "filename": "handbook.pdf",
    "mime_type": "application/pdf",
    "size_bytes": 204800
  }'
Step 2 — PUT the file bytes to the returned upload_urlbash
curl "$UPLOAD_URL" \
  -X PUT \
  -H "Content-Type: application/pdf" \
  --data-binary @handbook.pdf
Step 3 — commit the filebash
curl https://api.cortex.cognit-dx.com/v1/project-files/d7001e74-aee2-4b27-a2e5-7a54d5eec698/commit \
  -X POST \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
403Forbidden — only a project member can upload files.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
400Request body failed validation.`{ error, code, request_id }`
201 Createdjson
{
  "file_id": "d7001e74-aee2-4b27-a2e5-7a54d5eec698",
  "upload_url": "https://storage.example.com/cortex-documents/f1ba15e0-.../handbook.pdf?sv=2026-02-06&...",
  "expires_at": "2026-05-18T08:43:19.119Z"
}

Commit project file

Finalise a pending project file after the client has PUT the file bytes to the pre-signed upload URL. The server transitions the file's status from pending to ready AND, in the same database transaction, enqueues a `project_file.ingest` outbox command (`{ project_file_id }`) that the worker pipeline picks up to extract, chunk, and embed the file's content for project search. Only a project member may commit (creator counts as a member). Files already in a non-pending state return 409.

POST/v1/project-files/:id/commit

Path parameters

NameTypeRequiredDescription
idstringRequiredThe project file ID returned by POST /projects/:id/files/upload-url.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/project-files/d7001e74-aee2-4b27-a2e5-7a54d5eec698/commit \
  -X POST \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
403Forbidden — only a project member can commit this file.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
409The file is not in the `pending` state.`{ error, code, request_id }`
200 OKjson
{
  "id": "d7001e74-aee2-4b27-a2e5-7a54d5eec698",
  "organization_id": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815",
  "project_id": "9960c593-9a95-42a8-b26b-a50b4bd915e2",
  "filename": "handbook.pdf",
  "mime_type": "application/pdf",
  "size_bytes": 204800,
  "storage_key": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815/projects/9960c593-9a95-42a8-b26b-a50b4bd915e2/6560e315-ccac-4b9b-a193-da14eac9faaa/handbook.pdf",
  "status": "ready",
  "error": null,
  "content": null,
  "extractor": null,
  "extractor_version": null,
  "extracted_at": null,
  "index_status": "pending",
  "indexed_at": null,
  "uploaded_by": "39a69cb1-c14c-481d-85fb-fd43c8046440",
  "created_at": "2026-05-18T08:28:19.117Z",
  "updated_at": "2026-05-18T08:28:31.394Z"
}

List project files

List the files uploaded to a project. The caller must be able to access the project (its creator or an explicit member) — an org member who isn't on the project gets 404, the same as a nonexistent project. Tri-state filter on deleted state: omit `isDeleted` (or send `isDeleted=false`) to get only non-deleted files (`pending`, `ready`, `failed`); send `isDeleted=true` to get only soft-deleted files. Results are ordered newest first.

GET/v1/projects/:id/files

Path parameters

NameTypeRequiredDescription
idstringRequiredThe project ID whose files to list.

Query parameters

NameTypeRequiredDescription
isDeletedbooleanOptional`true` returns only soft-deleted files; `false` (or omitted) returns only non-deleted files.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/projects/9960c593-9a95-42a8-b26b-a50b4bd915e2/files \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
200 OKjson
{
  "data": [
    {
      "id": "d7001e74-aee2-4b27-a2e5-7a54d5eec698",
      "organization_id": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815",
      "project_id": "9960c593-9a95-42a8-b26b-a50b4bd915e2",
      "filename": "handbook.pdf",
      "mime_type": "application/pdf",
      "size_bytes": 204800,
      "status": "ready",
      "index_status": "pending",
      "created_at": "2026-05-18T08:28:19.117Z",
      "updated_at": "2026-05-18T08:28:31.394Z"
    }
  ]
}

Download project file

Generate a short-lived presigned GET URL for downloading a project file's underlying blob. The URL expires after 1 hour. The caller must be able to access the file's project (its creator or an explicit member). Returns 404 if the file does not exist, belongs to a different organization, has been soft-deleted, or the caller isn't on the project — all four cases are indistinguishable (deleted files 404 rather than 410 for the same reason).

GET/v1/project-files/:id/download

Path parameters

NameTypeRequiredDescription
idstringRequiredThe project file ID.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/project-files/d7001e74-aee2-4b27-a2e5-7a54d5eec698/download \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found, in a different organization, soft-deleted, or the caller can't access its project.`{ error, code, request_id }`
200 OKjson
{
  "download_url": "https://storage.example.com/cortex-documents/f1ba15e0-.../handbook.pdf?sv=2026-02-06&se=2026-05-21T11%3A30%3A00Z&sig=abc123..."
}

Delete project file

Soft-delete a project file (sets `status` to `deleted`); the row is retained but drops out of the default file list and download stops working. Only a project member may delete (creator counts as a member). Note: this does not remove the file's `project_file_chunks` rows — those are cleaned up by the worker's reindex path, not by delete itself — but Phase 2 search filters project files on `status = 'ready'`, so a deleted file's stale chunks never surface in search results in the meantime.

DELETE/v1/project-files/:id

Path parameters

NameTypeRequiredDescription
idstringRequiredThe project file ID to delete.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/project-files/d7001e74-aee2-4b27-a2e5-7a54d5eec698 \
  -X DELETE \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
403Forbidden — only a project member can delete this file.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
204 No Contenttext

Threads

List threads

Return the threads visible to the authenticated user within their organization (their own, plus project threads they can see), newest first, one page at a time. Filters are query parameters and are camelCase on the wire. Each thread carries its ID, title, source, project, pin state and timestamps.

GET/v1/threads

Query parameters

NameTypeRequiredDescription
searchstringOptionalCase-insensitive match on the title.
createdFromstringOptionalISO datetime; only threads created at or after it.
createdTostringOptionalISO datetime; only threads created at or before it.
projectIdstringOptionalOnly threads in this project.
createdByTypestringOptional"user", "agent" or "workflow".
createdByIdstringOptionalUUID of the user, agent or workflow that started the thread.
isPinnedbooleanOptional`true` for pinned threads only, `false` for unpinned only. The member app fetches pinned threads with this so they survive falling off the first page of recent chats.
limitintegerOptionalPage size, 1–100. Default 20.
cursorstringOptionalOpaque cursor from the previous page's `next_cursor`.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/threads \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
200 OKjson
{
  "data": [
    {
      "id": "e92f24b1-43b2-494d-a786-5bd4456f532c",
      "organization_id": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815",
      "created_by_type": "user",
      "created_by_id": "0ce6409a-3bfa-4e2f-883a-5a696b451d8b",
      "title": "User Greeting",
      "project_id": null,
      "is_pinned": false,
      "created_at": "2026-05-17T18:22:54.024Z",
      "updated_at": "2026-05-17T18:22:54.961Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Create thread

Create a new thread owned by the authenticated user. Call this endpoint before posting messages or starting a run — every message and run must belong to a thread. Optionally bind the thread to a specific agent by providing an agentId; when bound, each user message is automatically routed through the agent orchestrator instead of spawning a plain task. To create the thread inside a project, the caller must be able to access that project (its creator or an explicit project member) — otherwise the request returns 404, the same response as an unknown project id.

POST/v1/threads

Request body

NameTypeRequiredDescription
titlestringOptionalDisplay title for the thread. If omitted the title is null until auto-generated by the generate-thread-title endpoint. Maximum 255 characters.
projectIdstringOptionalOptional project UUID. When set, project members can access the thread.
createdByTypestringOptionalWho started the thread: "user" (default), "agent", or "workflow". For `user`, the server always uses the authenticated user as `createdById`. For `agent` or `workflow`, `createdById` must reference an active resource in the organization.
createdByIdstringOptionalUUID of the user, agent, or workflow that started the thread. Defaults to the authenticated user when `createdByType` is omitted or `user`.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/threads \
  -X POST \
  -H "Authorization: Bearer $CORTEX_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"title":"New chat"}'

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
400Request body failed validation.`{ error, code, request_id }`
404`projectId` does not reference a project the caller can access.`{ error, code, request_id }`
201 Createdjson
{
  "id": "92019e47-0d54-4d19-874a-f28c268cac78",
  "organization_id": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815",
  "created_by_type": "user",
  "created_by_id": "0ce6409a-3bfa-4e2f-883a-5a696b451d8b",
  "title": "Smoke test thread",
  "project_id": null,
  "is_pinned": false,
  "created_at": "2026-05-18T08:19:37.111Z",
  "updated_at": "2026-05-18T08:19:37.111Z"
}

Get thread

Fetch a single accessible thread by ID. The response includes `active_run_id`, which is the thread's current `running` or `awaiting` run, or null. Clients can use it to resume an in-flight response after a reload, in another tab, or when browser-local state was lost. Accessible means the authenticated user created the thread, has triggered a run on it, or is a member (or the creator) of the project it belongs to — anyone else gets 404, indistinguishable from a nonexistent thread.

GET/v1/threads/:id

Path parameters

NameTypeRequiredDescription
idstringRequiredThe thread ID.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/threads/9f7c9d3a-1234-5678-9abc-def012345678 \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
200 OKjson
{
  "id": "92019e47-0d54-4d19-874a-f28c268cac78",
  "organization_id": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815",
  "created_by_type": "user",
  "created_by_id": "0ce6409a-3bfa-4e2f-883a-5a696b451d8b",
  "title": "Smoke test thread",
  "project_id": null,
  "is_pinned": false,
  "created_at": "2026-05-18T08:19:37.111Z",
  "updated_at": "2026-05-18T08:19:37.111Z",
  "active_run_id": null
}

Update thread

Update an existing thread. Only `title`, `projectId` and `isPinned` are mutable — creator fields and audit timestamps cannot be patched after creation. Pass `title: null` to clear the title. Pinning is bookkeeping, not use: changing `isPinned` leaves `updated_at` alone, so a pinned or unpinned thread keeps its place in recency-ordered lists. Renaming/reassigning a thread is a closed set: the thread's user-type creator, or — for a project-scoped thread — a project admin (the project's creator counts as an implicit admin). A caller with no visibility into the thread at all gets 404; a caller who can see the thread (e.g. a plain project member) but isn't in that set gets 403.

PATCH/v1/threads/:id

Path parameters

NameTypeRequiredDescription
idstringRequiredThe thread ID to update.

Request body

NameTypeRequiredDescription
titlestringOptionalNew display title. Max 255 characters. Pass null to clear. Any other field is silently ignored.
projectIdstringOptionalMove the thread into a project the caller can access, or pass null to take it out of its project.
isPinnedbooleanOptionalPin (`true`) or unpin (`false`) the thread. Pinned threads are shown in their own section above recent chats in the member app. `is_pinned` on the wire.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/threads/9f7c9d3a-1234-5678-9abc-def012345678 \
  -X PATCH \
  -H "Authorization: Bearer $CORTEX_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"title":"Renamed thread"}'

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
403The thread is visible to the caller but they aren't the creator or a project admin.`{ error, code, request_id }`
404Resource not found, or not visible to the caller at all.`{ error, code, request_id }`
400Request body failed validation.`{ error, code, request_id }`
200 OKjson
{
  "id": "92019e47-0d54-4d19-874a-f28c268cac78",
  "organization_id": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815",
  "created_by_type": "user",
  "created_by_id": "0ce6409a-3bfa-4e2f-883a-5a696b451d8b",
  "title": "Renamed thread",
  "project_id": null,
  "is_pinned": false,
  "created_at": "2026-05-18T08:19:37.111Z",
  "updated_at": "2026-05-18T08:42:12.882Z"
}

Delete thread

Permanently delete a thread. All messages, attachments, artifacts, and run records belonging to the thread are cascaded by foreign-key constraints. Thread deletion is irreversible. Deletion is a closed set: the thread's user-type creator, or — for a project-scoped thread — a project admin (the project's creator counts as an implicit admin). A caller with no visibility into the thread gets 404; a caller who can see it (e.g. a plain project member) but isn't in that set gets 403. Returns 204 No Content on success.

DELETE/v1/threads/:id

Path parameters

NameTypeRequiredDescription
idstringRequiredThe thread ID to delete.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/threads/9f7c9d3a-1234-5678-9abc-def012345678 \
  -X DELETE \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
403The thread is visible to the caller but they aren't the creator or a project admin.`{ error, code, request_id }`
404Resource not found, or not visible to the caller at all.`{ error, code, request_id }`
204 No Contenttext

Generate thread title

Generate a short AI-written title (3–6 words) from a single message and save it on the thread. Calls Claude Haiku directly (not the worker pipeline) for fast, cheap inference. Idempotent in two cases: if the thread already has a non-empty title, the request is a no-op and the existing thread is returned unchanged; if the server is missing an Anthropic API key, the request is also a no-op (silent fallback so a missing key never blocks the chat UI). Wrapping quotes and trailing punctuation are stripped from the model output. Same authorization as PATCH /threads/:id: the thread's creator or (for a project-scoped thread) a project admin; a visible-but-unauthorized caller gets 403, an invisible thread gets 404.

POST/v1/threads/:id/generate-title

Path parameters

NameTypeRequiredDescription
idstringRequiredThe thread ID to title.

Request body

NameTypeRequiredDescription
messagestringRequiredSource text used to generate the title — typically the user's first message in the thread. 1–4000 characters.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/threads/9f7c9d3a-1234-5678-9abc-def012345678/generate-title \
  -X POST \
  -H "Authorization: Bearer $CORTEX_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"message":"Summarize the Q1 pipeline."}'

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
403The thread is visible to the caller but they aren't the creator or a project admin.`{ error, code, request_id }`
404Resource not found, or not visible to the caller at all.`{ error, code, request_id }`
400Request body failed validation.`{ error, code, request_id }`
200 OKjson
{
  "id": "92019e47-0d54-4d19-874a-f28c268cac78",
  "organization_id": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815",
  "created_by_type": "user",
  "created_by_id": "0ce6409a-3bfa-4e2f-883a-5a696b451d8b",
  "title": "Draft launch announcement",
  "project_id": null,
  "is_pinned": false,
  "created_at": "2026-05-18T08:19:37.111Z",
  "updated_at": "2026-05-18T08:21:04.118Z"
}

Messages

List messages

Return messages in a thread ordered by sequence number ascending. The response is cursor-paginated; follow `next_cursor` while `has_more` is true to read the complete transcript. Run output messages include `run_id`. Inaccessible threads return 404.

GET/v1/threads/:id/messages

Path parameters

NameTypeRequiredDescription
idstringRequiredThe thread ID whose messages to list.

Query parameters

NameTypeRequiredDescription
limitnumberOptionalPage size from 1 to 100. Defaults to 20.
cursorstringOptionalOpaque cursor returned as `next_cursor` by the previous page.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/threads/9f7c9d3a-1234-5678-9abc-def012345678/messages \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
200 OKjson
{
  "data": [
    {
      "id": "msg_01jz4n2x8k8g9d0k6x2f4v7q3a",
      "thread_id": "92019e47-0d54-4d19-874a-f28c268cac78",
      "role": "user",
      "created_by_type": "user",
      "created_by_id": "0ce6409a-3bfa-4e2f-883a-5a696b451d8b",
      "content": "Hello, Cortex.",
      "content_blocks": [
        {
          "type": "text",
          "text": "Hello, Cortex."
        }
      ],
      "sequence": 1,
      "created_at": "2026-05-18T08:20:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Post message

Post a message to a thread. Accepts `role: "user"` or `role: "system"`. **User role (auto-trigger):** When `role: "user"` is sent, the server inserts the message and immediately creates a `conversation_run` (status: `queued`) and emits a worker event to start processing. The response is `{ message, run: { id, status } }`. This is the primary way to send a chat message and trigger execution. **Resuming an awaiting run:** if the thread's active run is paused (`awaiting`) at a clarification interrupt (an act called `ask_user`) and the author is the run's originator, this message is treated as the answer: it resumes that run (response `{ message, run: { id, status: "running" }, queued: false }`) instead of starting a new one. The question itself is durable: when the run paused, the worker persisted it as an `assistant` message whose `content_blocks` carry an `act` block (`kind: "question"`, with `body.text`, `body.options`, `body.multi_select`); on resume the answer is stamped onto that block as `body.answer`, so transcripts always show what was asked and what was chosen. Messages from other users, or additional messages while a run is active, are stored `pending` and queued (`{ message, run: null, queued: true }`). If the organization has data-leakage-protection rules, the message content is evaluated BEFORE it is stored or dispatched: a blocked message returns 422 with code `dlp_blocked` and is never persisted or sent to a model. **System role (no trigger):** When `role: "system"` is sent, the message is written to the thread's transcript as context for the next run but no run is created. The response is `{ message }`. Use this to inject runtime hints, caller identity, or feature flags before explicitly starting a run. `assistant` and `tool` messages are written only by the worker — clients cannot post them. Returns 201 with the message (and run, when role is user).

POST/v1/threads/:id/messages

Path parameters

NameTypeRequiredDescription
idstringRequiredThe thread ID.

Request body

NameTypeRequiredDescription
rolestringRequired`"user"` to post a user message and auto-trigger a run; `"system"` to inject context without triggering. Any other value is rejected with 400.
contentstringRequiredPlain-text message content. Min 1 character.
contentBlocksarrayOptionalStructured content blocks for multimodal messages. Optional — when omitted the server derives a single text block from `content`.
attachmentIdsarrayOptionalUUIDs of thread attachments to include with this message. Only applies when `role: "user"`. The legacy alias `documentIds` is still accepted.
agentIdstringOptionalUUID of an agent to route this run to. Only applies when `role: "user"`.
workflowIdstringOptionalUUID of a workflow to execute for this run. Only applies when `role: "user"`. Mutually exclusive with `agentId`.
User message (auto-triggers a run)bash
curl https://api.cortex.cognit-dx.com/v1/threads/9f7c9d3a/messages \
  -H "Authorization: Bearer $CORTEX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"role": "user", "content": "Summarise the Q1 pipeline."}'
System message (no run triggered)bash
curl https://api.cortex.cognit-dx.com/v1/threads/9f7c9d3a/messages \
  -H "Authorization: Bearer $CORTEX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"role": "system", "content": "The caller is acting on behalf of the launch-readiness review."}'
201 Created — user role response (includes run)json
{
  "message": {
    "id": "msg_01jz4n2x8k8g9d0k6x2f4v7q3a",
    "thread_id": "9f7c9d3a",
    "role": "user",
    "created_by_type": "user",
    "created_by_id": "0ce6409a-3bfa-4e2f-883a-5a696b451d8b",
    "content": "Summarise the Q1 pipeline.",
    "content_blocks": [{ "type": "text", "text": "Summarise the Q1 pipeline." }],
    "sequence": 5,
    "created_at": "2026-05-17T10:24:31.000Z"
  },
  "run": {
    "id": "43f6a165-46a6-4e68-9de8-68201c7f4421",
    "status": "queued"
  }
}

Update system message

Edit the plain-text content of a **system** message (the ones you injected via `POST /threads/:id/messages`). Use this when you need to amend an injected note before the next run. Editing the content of a user/assistant message returns 403 `non_system_content_immutable` — those messages are the durable model/user transcript and must not be rewritten by the API. The owning thread must belong to the authenticated user; another user's message returns 404.

PATCH/v1/messages/:id

Path parameters

NameTypeRequiredDescription
idstringRequiredThe message ID to update.

Request body

NameTypeRequiredDescription
contentstringOptionalReplacement plain-text content. System messages only — patching `content` on a user/assistant message returns 403 `non_system_content_immutable`. Min 1 character.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/messages/9f7c9d3a-1234-5678-9abc-def012345678 \
  -X PATCH \
  -H "Authorization: Bearer $CORTEX_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"content":"Hello, Cortex."}'

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
422Request body failed validation.`{ error, code, request_id }`
200 OK — the updated messagejson
{
  "id": "msg_01jz4n2x8k8g9d0k6x2f4v7q3a",
  "thread_id": "92019e47-0d54-4d19-874a-f28c268cac78",
  "role": "system",
  "created_by_type": "user",
  "created_by_id": "0ce6409a-3bfa-4e2f-883a-5a696b451d8b",
  "content": "Updated context note.",
  "content_blocks": [
    {
      "type": "text",
      "text": "Updated context note."
    }
  ],
  "sequence": 4,
  "created_at": "2026-05-18T08:20:00.000Z"
}

Delete message

Permanently remove a single message from the transcript. Messages referenced as a run's durable output cannot be deleted; those return 409 `run_output_immutable` so a terminal run never loses its reply. The owning thread must be accessible to the authenticated user; inaccessible messages return 404. Returns 204 No Content on success; a repeat delete returns 404.

DELETE/v1/messages/:id

Path parameters

NameTypeRequiredDescription
idstringRequiredThe message ID to delete.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/messages/9f7c9d3a-1234-5678-9abc-def012345678 \
  -X DELETE \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
409The message is a run's durable output.`{ error, code: 'run_output_immutable', request_id }`
204 No Contenttext

Attachments

Create upload URL

Initiate a two-step direct-to-storage upload for a user attachment. Step 1 — call this endpoint to create a pending attachment record and receive a pre-signed PUT URL. Step 2 — PUT the raw file bytes directly to that URL (no Authorization header; the signature is embedded in the URL). Step 3 — call POST /attachments/:id/commit to mark the attachment ready. The pre-signed URL expires in 15 minutes; if the PUT is not completed within that window, discard the attachment ID and start over.

POST/v1/attachments/upload-url

Request body

NameTypeRequiredDescription
threadIdstringRequiredUUID of the thread this attachment will belong to.
filenamestringRequiredOriginal file name including extension. Maximum 255 characters.
mimeTypestringRequiredMIME type of the file, e.g. application/pdf or image/png. Maximum 100 characters.
sizeBytesnumberRequiredFile size in bytes. Must be a positive integer.
Step 1 — request a pre-signed upload URLbash
curl https://api.cortex.cognit-dx.com/v1/attachments/upload-url \
  -X POST \
  -H "Authorization: Bearer $CORTEX_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
    "thread_id": "16000e2f-6aab-45fc-937b-3684b8cd9722",
    "filename": "report.pdf",
    "mime_type": "application/pdf",
    "size_bytes": 1024
  }'
Step 2 — PUT the file bytes to the returned upload_urlbash
curl "$UPLOAD_URL" \
  -X PUT \
  -H "Content-Type: application/pdf" \
  --data-binary @report.pdf
Step 3 — commit the attachmentbash
curl https://api.cortex.cognit-dx.com/v1/attachments/d7001e74-aee2-4b27-a2e5-7a54d5eec698/commit \
  -X POST \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
422Request body failed validation.`{ error, code, request_id }`
201 Createdjson
{
  "attachment_id": "d7001e74-aee2-4b27-a2e5-7a54d5eec698",
  "upload_url": "https://storage.example.com/cortex-documents/f1ba15e0-.../smoke.pdf?sv=2026-02-06&...",
  "expires_at": "2026-05-18T08:43:19.119Z"
}

Commit attachment

Finalise a pending attachment after the client has successfully PUT the file bytes to the pre-signed upload URL. The server transitions the attachment's status from pending to ready, making it available for context assembly, search, and download. Calling commit before the blob has been uploaded is valid (the storage backend does not gate the status transition), but the attachment will be unusable until the bytes are present. Attachments already in a non-pending state return 409.

POST/v1/attachments/:id/commit

Path parameters

NameTypeRequiredDescription
idstringRequiredThe attachment ID returned by POST /attachments/upload-url.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/attachments/9f7c9d3a-1234-5678-9abc-def012345678/commit \
  -X POST \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
422Request body failed validation.`{ error, code, request_id }`
200 OKjson
{
  "id": "d7001e74-aee2-4b27-a2e5-7a54d5eec698",
  "organization_id": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815",
  "thread_id": "1a67318e-4021-4b10-8585-22ed5b5ead56",
  "filename": "smoke.pdf",
  "mime_type": "application/pdf",
  "size_bytes": 1024,
  "source_type": "upload",
  "source_ref": {},
  "storage_key": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815/1a67318e-4021-4b10-8585-22ed5b5ead56/6560e315-ccac-4b9b-a193-da14eac9faaa/smoke.pdf",
  "metadata": {},
  "status": "ready",
  "error": null,
  "created_at": "2026-05-18T08:28:19.117Z",
  "updated_at": "2026-05-18T08:28:31.394Z"
}

Download attachment

Generate a short-lived presigned GET URL for downloading an attachment's underlying file. The URL expires after 1 hour. Returns 404 if the attachment does not exist or belongs to a different organization, and 410 if the attachment has been soft-deleted.

GET/v1/attachments/:id/download

Path parameters

NameTypeRequiredDescription
idstringRequiredThe id value from the endpoint path.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/attachments/9f7c9d3a-1234-5678-9abc-def012345678/download \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
200 OKjson
{
  "download_url": "https://storage.example.com/cortex-documents/f1ba15e0-.../smoke.pdf?sv=2026-02-06&se=2026-05-21T11%3A30%3A00Z&sig=abc123..."
}

List thread attachments

List non-deleted user uploads for a thread. By default returns root-level attachments (`parent_id` is null). Pass `parent_id` to list children of a zip or archive bundle.

GET/v1/threads/:id/attachments

Path parameters

NameTypeRequiredDescription
idstringRequiredThe id value from the endpoint path.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/threads/16000e2f-6aab-45fc-937b-3684b8cd9722/attachments \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
200 OKjson
{
  "data": [
    {
      "id": "d7001e74-aee2-4b27-a2e5-7a54d5eec698",
      "organization_id": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815",
      "thread_id": "1a67318e-4021-4b10-8585-22ed5b5ead56",
      "parent_id": null,
      "filename": "report.pdf",
      "mime_type": "application/pdf",
      "size_bytes": 204800,
      "storage_key": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815/1a67318e-4021-4b10-8585-22ed5b5ead56/report.pdf",
      "status": "ready",
      "error": null,
      "created_at": "2026-05-21T10:15:00.000Z",
      "updated_at": "2026-05-21T10:15:22.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Get attachment

Get a single attachment's metadata by ID. Returns 404 if the attachment does not exist or belongs to a different organization.

GET/v1/attachments/:id

Path parameters

NameTypeRequiredDescription
idstringRequiredThe id value from the endpoint path.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/attachments/9f7c9d3a-1234-5678-9abc-def012345678 \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
200 OKjson
{
  "id": "d7001e74-aee2-4b27-a2e5-7a54d5eec698",
  "organization_id": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815",
  "thread_id": "1a67318e-4021-4b10-8585-22ed5b5ead56",
  "filename": "smoke.pdf",
  "mime_type": "application/pdf",
  "size_bytes": 204800,
  "source_type": "upload",
  "source_ref": {},
  "storage_key": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815/1a67318e-4021-4b10-8585-22ed5b5ead56/6560e315-ccac-4b9b-a193-da14eac9faaa/smoke.pdf",
  "metadata": {},
  "status": "ready",
  "error": null,
  "created_at": "2026-05-21T10:15:00.000Z",
  "updated_at": "2026-05-21T10:15:22.000Z"
}

Delete attachment

Soft-delete an attachment by setting its status to `deleted`. The underlying blob is not immediately purged. Returns 204 on success. Returns 404 if the attachment does not exist or belongs to a different organization.

DELETE/v1/attachments/:id

Path parameters

NameTypeRequiredDescription
idstringRequiredThe id value from the endpoint path.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/attachments/9f7c9d3a-1234-5678-9abc-def012345678 \
  -X DELETE \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
204 No Contenttext

Runs

Create run

Explicit run creation. Atomically inserts a user message (using `input.content`) and creates a `conversation_run`. Use this endpoint when you want finer-grained control than the auto-trigger on `POST /threads/:id/messages { role: "user" }` — for example, when you need to specify `agentId` or `workflowId` without coupling that choice to the message post. Returns 201 with `{ run, message }`.

POST/v1/threads/:id/runs

Path parameters

NameTypeRequiredDescription
idstringRequiredThe thread ID to create the run in.

Request body

NameTypeRequiredDescription
inputobjectOptionalInput for the run. Shape: `{ content: string, contentBlocks?: array }`. Creates a user message from `content` and queues a run.
agentIdstringOptionalUUID of an agent to route the run to. When omitted, the run uses chat mode unless `workflowId` is set.
workflowIdstringOptionalUUID of a workflow to execute. Mutually exclusive with `agentId`. When provided, the classifier is skipped. `model`, `tool`, prompt-style `skill`, `agent`, and nested `workflow` steps run through the worker graph.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/threads/9f7c9d3a-1234-5678-9abc-def012345678/runs \
  -X POST \
  -H "Authorization: Bearer $CORTEX_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"input":{},"agent_id":"9f7c9d3a-1234-5678-9abc-def012345678","workflow_id":"9f7c9d3a-1234-5678-9abc-def012345678"}'

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
422Request body failed validation.`{ error, code, request_id }`
201 Createdjson
{
  "run": {
    "id": "43f6a165-46a6-4e68-9de8-68201c7f4421",
    "thread_id": "9f7c9d3a",
    "status": "queued",
    "mode": "chat",
    "created_at": "2026-05-17T10:24:31.000Z"
  },
  "message": {
    "id": "msg_01jz4n2x8k8g9d0k6x2f4v7q3a",
    "thread_id": "9f7c9d3a",
    "role": "user",
    "content": "Summarise the Q1 pipeline.",
    "sequence": 5,
    "created_at": "2026-05-17T10:24:31.000Z"
  }
}

Get run state

Return the durable catch-up snapshot for a run: the run record, complete act DAG, current partial text for running acts, artifacts, and the final output message when present. A terminal run is delivered only when both `output_message_id` and `output_message` are present. This is the authoritative state clients should check after any terminal SSE hint.

GET/v1/threads/:id/runs/:runId

Path parameters

NameTypeRequiredDescription
idstringRequiredThe thread ID that owns the run.
runIdstringRequiredThe run ID to fetch state for.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/threads/9f7c9d3a-1234-5678-9abc-def012345678/runs/43f6a165-46a6-4e68-9de8-68201c7f4421 \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
200 OKjson
{
  "id": "43f6a165-46a6-4e68-9de8-68201c7f4421",
  "organization_id": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815",
  "thread_id": "16000e2f-6aab-45fc-937b-3684b8cd9722",
  "input_message_id": "msg_01jz4n2x8k8g9d0k6x2f4v7q3a",
  "output_message_id": "msg_01jz4n2x8k8g9d0k6x2f4v7q3b",
  "created_by_type": "user",
  "created_by_id": "0ce6409a-3bfa-4e2f-883a-5a696b451d8b",
  "status": "completed",
  "created_at": "2026-05-18T08:23:25.127Z",
  "updated_at": "2026-05-18T08:23:31.042Z",
  "acts": [
    {
      "id": "9b2f7d3a-1234-5678-9abc-def012345678",
      "key": "research",
      "status": "completed",
      "depends_on": [],
      "description": "Research the request",
      "response": "Research complete.",
      "error": null,
      "partial": null
    }
  ],
  "artifacts": [],
  "output_message": {
    "id": "msg_01jz4n2x8k8g9d0k6x2f4v7q3b",
    "content": "Here is the completed result."
  }
}

Stream run events

Open the run's snapshot-plus-live Server-Sent Events stream. The API subscribes to Redis Pub/Sub first, sends one `snapshot` frame containing the durable PostgreSQL state, then forwards ephemeral token, activity, act, artifact, interrupt, error, and lifecycle events. There is no replay cursor or `Last-Event-ID` support. Reconnect to the same URL and rebuild from the next snapshot. After a terminal lifecycle hint, confirm delivery with `GET /threads/:id/runs/:runId` and require terminal status plus a readable output message.

GET/v1/threads/:id/runs/:runId/events

Path parameters

NameTypeRequiredDescription
idstringRequiredThe thread ID that owns the run.
runIdstringRequiredThe run ID whose events to stream.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/threads/:id/runs/:runId/events \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
200 text/event-streamtext
event: snapshot
data: {"id":"43f6a165-46a6-4e68-9de8-68201c7f4421","threadId":"16000e2f-6aab-45fc-937b-3684b8cd9722","status":"running","outputMessageId":null,"acts":[],"artifacts":[],"outputMessage":null}

event: tokens.delta
data: {"channel":"tokens","type":"tokens.delta","actId":"9b2f7d3a-1234-5678-9abc-def012345678","payload":{"text":"Hello"},"ts":1751879000.12}

: keepalive

Cancel run

Cancel an in-flight or awaiting run. Takes no body. In one transaction the API persists an assistant cancellation reply, links it through `output_message_id`, marks the run cancelled, and enqueues worker cleanup. The worker then cancels active acts and drains the next queued turn. Returns 202 with the already-cancelled run; 409 if the run was already terminal.

POST/v1/threads/:id/runs/:runId/cancel

Path parameters

NameTypeRequiredDescription
idstringRequiredThe thread ID that owns the run.
runIdstringRequiredThe run ID to cancel.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/threads/9f7c9d3a-1234-5678-9abc-def012345678/runs/43f6a165-46a6-4e68-9de8-68201c7f4421/cancel \
  -X POST \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
202Cancellation persisted and worker cleanup queued.`{ run, cancellation: { status: "cancelled" } }`
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
409Run is already terminal.`{ error, code, request_id }`
422Request body failed validation.`{ error, code, request_id }`
202 Acceptedjson
{
  "run": {
    "id": "43f6a165-46a6-4e68-9de8-68201c7f4421",
    "status": "cancelled",
    "output_message_id": "msg_01jz4n2x8k8g9d0k6x2f4v7q3b"
  },
  "cancellation": {
    "status": "cancelled"
  }
}

Approve run

Approve a run that is paused (`awaiting`) at an approval interrupt — i.e. an act that called `request_approval`. The API queues a resume command and the worker continues the act from where it paused, informing the model the action was approved. Pass `interruptId` (the awaiting act's ID) to target a specific gate; if omitted, the run's newest awaiting act is used. Returns 202 `{ run: { id, status: "running" } }`; 409 if the run is not awaiting.

POST/v1/threads/:id/runs/:runId/approve

Path parameters

NameTypeRequiredDescription
idstringRequiredThe thread ID that owns the run.
runIdstringRequiredThe run ID to approve.

Request body

NameTypeRequiredDescription
interruptIdstringOptionalOptional awaiting act ID to approve. If omitted, the run's newest awaiting act is used.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/threads/9f7c9d3a-1234-5678-9abc-def012345678/runs/43f6a165-46a6-4e68-9de8-68201c7f4421/approve \
  -X POST \
  -H "Authorization: Bearer $CORTEX_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"interruptId":"workflow:approve"}'

Response codes

StatusMeaningBody
202Approval accepted and resume queued.`{ run: { id, status: "running" } }`
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
409Run has no active approval gate (not awaiting).`{ error, code, request_id }`
422Request body failed validation.`{ error, code, request_id }`
202 Acceptedjson
{
  "run": {
    "id": "43f6a165-46a6-4e68-9de8-68201c7f4421",
    "status": "running"
  }
}

Reject run

Reject a run that is paused (`awaiting`) at an approval interrupt. The API queues a resume command; the worker resumes the act and informs the model the action was declined, so it completes gracefully without performing the action (a soft decline — the act is not failed). Pass `interruptId` (the awaiting act's ID) to target a specific gate, and an optional `reason`. Returns 202 `{ run: { id, status: "running" } }`; 409 if the run is not awaiting.

POST/v1/threads/:id/runs/:runId/reject

Path parameters

NameTypeRequiredDescription
idstringRequiredThe thread ID that owns the run.
runIdstringRequiredThe run ID to reject.

Request body

NameTypeRequiredDescription
interruptIdstringOptionalOptional awaiting act ID to reject. If omitted, the run's newest awaiting act is used.
reasonstringOptionalOptional human-readable reason for the rejection.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/threads/9f7c9d3a-1234-5678-9abc-def012345678/runs/43f6a165-46a6-4e68-9de8-68201c7f4421/reject \
  -X POST \
  -H "Authorization: Bearer $CORTEX_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"interruptId":"workflow:approve"}'

Response codes

StatusMeaningBody
202Rejection accepted and resume queued.`{ run: { id, status: "running" } }`
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
409Run has no active approval gate (not awaiting).`{ error, code, request_id }`
422Request body failed validation.`{ error, code, request_id }`
202 Acceptedjson
{
  "run": {
    "id": "43f6a165-46a6-4e68-9de8-68201c7f4421",
    "status": "running"
  }
}

Artifacts

List thread artifacts

List run-generated artifacts for a thread. Artifacts are durable files produced by tools during a run. Each item includes a typed `type` field (`dashboard`, `image`, `presentation`, `spreadsheet`, `document`, `file`) inferred from MIME type and extension, plus optional source fields (`code`, `content`, `generator`, `generator_version`, `prompt`, `model`).

GET/v1/threads/:id/artifacts

Path parameters

NameTypeRequiredDescription
idstringRequiredThe id value from the endpoint path.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/threads/16000e2f-6aab-45fc-937b-3684b8cd9722/artifacts \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
200 OKjson
{
  "data": [
    {
      "id": "d7001e74-aee2-4b27-a2e5-7a54d5eec698",
      "organization_id": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815",
      "thread_id": "1a67318e-4021-4b10-8585-22ed5b5ead56",
      "run_id": "43f6a165-46a6-4e68-9de8-68201c7f4421",
      "created_by_tool": "create_html_artifact",
      "type": "dashboard",
      "title": "Weekly sales dashboard",
      "description": null,
      "filename": "sales-dashboard.html",
      "mime_type": "text/html",
      "size_bytes": 204800,
      "storage_key": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815/1a67318e-4021-4b10-8585-22ed5b5ead56/sales-dashboard.html",
      "status": "ready",
      "code": "<!DOCTYPE html><html><body><h1>Weekly sales</h1></body></html>",
      "content": null,
      "generator": null,
      "generator_version": null,
      "prompt": null,
      "model": null,
      "created_at": "2026-05-21T10:15:00.000Z",
      "updated_at": "2026-05-21T10:15:22.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Get artifact

Get a single artifact by ID. Returns the same shape as the list endpoint. Returns 404 if the artifact does not exist or belongs to a different organization.

GET/v1/artifacts/:id

Path parameters

NameTypeRequiredDescription
idstringRequiredThe id value from the endpoint path.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/artifacts/9f7c9d3a-1234-5678-9abc-def012345678 \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
200 OKjson
{
  "id": "d7001e74-aee2-4b27-a2e5-7a54d5eec698",
  "organization_id": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815",
  "thread_id": "1a67318e-4021-4b10-8585-22ed5b5ead56",
  "parent_id": null,
  "run_id": "43f6a165-46a6-4e68-9de8-68201c7f4421",
  "created_by_tool": "create_html_artifact",
  "type": "dashboard",
  "title": "Weekly sales dashboard",
  "description": null,
  "filename": "sales-dashboard.html",
  "mime_type": "text/html",
  "size_bytes": 204800,
  "storage_key": "f1ba15e0-ebe8-4187-afe6-03ccb25b8815/1a67318e-4021-4b10-8585-22ed5b5ead56/sales-dashboard.html",
  "status": "ready",
  "code": "<!DOCTYPE html><html><body><h1>Weekly sales</h1></body></html>",
  "content": null,
  "generator": null,
  "generator_version": null,
  "prompt": null,
  "model": null,
  "created_at": "2026-05-21T10:15:00.000Z",
  "updated_at": "2026-05-21T10:15:22.000Z"
}

Download artifact

Generate a short-lived presigned GET URL for downloading an artifact's underlying file. The URL expires after 1 hour. Returns 404 if the artifact does not exist or belongs to a different organization.

GET/v1/artifacts/:id/download

Path parameters

NameTypeRequiredDescription
idstringRequiredThe id value from the endpoint path.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/artifacts/9f7c9d3a-1234-5678-9abc-def012345678/download \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
200 OKjson
{
  "download_url": "https://storage.example.com/cortex-documents/f1ba15e0-.../sales-dashboard.html?sv=2026-02-06&se=2026-05-21T11%3A30%3A00Z&sig=abc123..."
}

Delete artifact

Soft-delete an artifact by setting its status to `deleted`. The underlying blob is not immediately purged. Returns 204 on success. Returns 404 if the artifact does not exist or belongs to a different organization.

DELETE/v1/artifacts/:id

Path parameters

NameTypeRequiredDescription
idstringRequiredThe id value from the endpoint path.
Example requestbash
curl https://api.cortex.cognit-dx.com/v1/artifacts/9f7c9d3a-1234-5678-9abc-def012345678 \
  -X DELETE \
  -H "Authorization: Bearer $CORTEX_TOKEN"

Response codes

StatusMeaningBody
401Missing or invalid credential.`{ error, code, request_id }`
404Resource not found in the caller's organization.`{ error, code, request_id }`
204 No Contenttext