ChatKit (beta) — sessions, threads, items
Status: DOCUMENTED · BETA (OpenAI-Beta: chatkit_beta=v1) · GET /v1/chatkit/threads LIVE_VERIFIED (200, empty) · GET /v1/chatkit/threads/{id} LIVE_DISCOVERED (404 invalid_request_error "ChatKit Thread with id 'cthr_doesnotexist' not found.") · session creation not run (needs an Agent Builder workflow id). The hosted-workflow path depends on Agent Builder, which shuts down 2026-11-30; ChatKit itself remains available via the self-hosted "advanced integration".
Sources: ChatKit guide · Advanced integrations · Reference: beta/chatkit (sessions create, cancel; threads list, retrieve, delete, list_items) · Actions · Widgets · Themes · OpenAPI openapi-master.yaml (/chatkit/**, group chatkit, beta: true).
Last verified: 2026-09-18.
What it is
ChatKit is an embeddable chat UI (JS SDK @openai/chatkit, Python server SDK openai-chatkit). Two integration paths:
| Path | Backend | API surface in this doc |
|---|---|---|
| Hosted workflow (transition window only) | Agent Builder workflow (workflow.id, versioned) run by OpenAI |
POST /v1/chatkit/sessions (mint a client_secret for the browser), thread inspection endpoints |
| Custom server (recommended for new work) | Your ChatKitServer (respond() streams events; stream_agent_response bridges the Agents SDK) |
none of the endpoints below — your server owns storage/threads |
Endpoints (https://api.openai.com/v1, header OpenAI-Beta: chatkit_beta=v1)
| Method & path | operationId | Request | Response | SDK |
|---|---|---|---|---|
POST /chatkit/sessions |
CreateChatSessionMethod |
CreateChatSessionBody: workflow{id*, version, state_variables{}, tracing{enabled}}, user* (opaque end-user id, scopes threads), expires_after{anchor:"created_at", seconds 1–600} (default 10 min), rate_limits{max_requests_per_1_minute} (default 10), chatkit_configuration{automatic_thread_titling{enabled}, file_upload{enabled, max_file_size ≤512 MB, max_files}, history{enabled, recent_threads}} |
chatkit.session: id (cksess_…), client_secret, expires_at, workflow{id,version,state_variables,tracing}, user, rate_limits, max_requests_per_1_minute, status active·expired·cancelled, chatkit_configuration |
client.beta.chatkit.sessions.create() |
POST /chatkit/sessions/{session_id}/cancel |
CancelChatSessionMethod |
— | session with status:"cancelled" (client secret stops working) |
.sessions.cancel() |
GET /chatkit/threads |
ListThreadsMethod |
limit (0–100, default 20), order (asc·desc), after, before, user (filter, 1–512 chars) |
{object:list, data:[chatkit.thread], first_id, last_id, has_more} |
.threads.list() |
GET /chatkit/threads/{thread_id} |
GetThreadMethod |
— | `chatkit.thread {id (cthr_…), created_at, title, status: active | locked{reason} |
DELETE /chatkit/threads/{thread_id} |
DeleteThreadMethod |
— | chatkit.thread.deleted (items + attachments removed) |
.threads.delete() |
GET /chatkit/threads/{thread_id}/items |
ListThreadItemsMethod |
limit, order, after, before |
list of chatkit.thread_item |
.threads.list_items() |
Auth: standard Authorization: Bearer API key. Spec marks every operation beta: true; the curl examples all send OpenAI-Beta: chatkit_beta=v1 (live list call with that header → 200).
Objects
chatkit.thread_itemunion (type):chatkit.user_message{content:[input_text{text} | quoted_text{text}], attachments[{type image·file, id, name, mime_type, preview_url}], inference_options{tool_choice, model}}·chatkit.assistant_message{content:[output_text{text, annotations:[file{source{filename}} | url{source{url}}]}]}·chatkit.widget{widget (serialized)}·chatkit.client_tool_call{status in_progress·completed, call_id, name, arguments (JSON string), output}·chatkit.task{task_type custom·thought, heading, summary}·chatkit.task_group{tasks[]}. All carryid (cthi_…), object, created_at, thread_id.- Note the spec examples show legacy item
typevaluesuser_message/assistant_messagein sample responses while the schema constants arechatkit.user_message/chatkit.assistant_message— treat the schema as authoritative, verify live when threads exist.
Security notes
client_secret is short-lived (≤600 s) and is the browser credential; never expose the API key to the frontend. user must be a unique authenticated end-user id — it isolates thread history. Cancel a session to invalidate its secret.
Live verification (2026-09-18)
| Call | Result |
|---|---|
GET /v1/chatkit/threads?limit=5 + OpenAI-Beta: chatkit_beta=v1 |
200 {"object":"list","data":[],"first_id":null,"has_more":false,"last_id":null} |
GET /v1/chatkit/threads/cthr_doesnotexist |
404 {"error":{"message":"ChatKit Thread with id 'cthr_doesnotexist' not found.","type":"invalid_request_error","param":null,"code":null}} |
POST /v1/chatkit/sessions |
not run (requires a workflow id; Agent Builder is being retired) — UNVERIFIED |