Chat API
The Chat API enables you to create chat sessions, send messages, and receive responses from your AI agents programmatically.
Base Authentication
All examples in this page assume:
x-api-key: YOUR_API_KEY
List Published Agents
Retrieve all published agents available in your workspace.
Endpoint: GET /api/v1/chats/published-agents
Request
curl -X GET "https://api.codeer.ai/api/v1/chats/published-agents" \
-H "x-api-key: YOUR_API_KEY"
Response
{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Customer Support Agent",
"description": "Handles customer inquiries",
"workspace_id": "workspace-uuid-here",
"publish_state": "public",
"agent_type": "basic",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
],
"message": null,
"error_code": 0
}
Response Fields
The response includes additional fields like system_prompt, unified_tools, suggested_questions, use_search, meta, llm_model, and versioning fields. See the full schema in the codebase for complete details.
Create Chat
Create a new chat session with a specific agent.
Endpoint: POST /api/v1/chats
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Chat session name (max 256 characters) |
agent_id |
UUID | Yes | The agent's ID in the current workspace |
external_user_id |
string | Conditional | Your system's user identifier. Required if workspace has whitelist mode enabled. |
Agent Must Be Published
Chat creation accepts any valid workspace agent_id, but sending messages requires the agent to have a published version. If the agent has no published version, later message requests return 404 Not Found with message Agent version not found. Use the List Published Agents endpoint to fetch publish-ready agent IDs.
Example
curl -X POST "https://api.codeer.ai/api/v1/chats" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Support Session",
"agent_id": "550e8400-e29b-41d4-a716-446655440000",
"external_user_id": "user_123"
}'
Response
{
"data": {
"id": 12345,
"name": "Support Session",
"meta": {
"external_user_id": "user_123",
"conversation_agent_id": "550e8400-e29b-41d4-a716-446655440000"
},
"external_user_id": "user_123",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
},
"message": null,
"error_code": 0
}
List Chats
Retrieve chat sessions with pagination and filtering.
Endpoint: GET /api/v1/chats
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
integer | 50 | Results per page (max 1000) |
offset |
integer | 0 | Number of results to skip |
order_by |
string | -created_at |
Sort order: created_at, -created_at, asc, desc |
agent_id |
UUID | - | Filter by agent |
external_user_id |
string | - | Filter by external user |
Example
curl -X GET "https://api.codeer.ai/api/v1/chats?limit=10&agent_id=550e8400-e29b-41d4-a716-446655440000" \
-H "x-api-key: YOUR_API_KEY"
Response
{
"data": [
{
"id": 12345,
"name": "Support Session",
"meta": { ... },
"external_user_id": "user_123",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:35:00Z"
}
],
"pagination": {
"limit": 10,
"offset": 0,
"total_records": 100,
"total_pages": 10,
"current_page": 1,
"next_page": "https://api.codeer.ai/api/v1/chats?offset=10&limit=10",
"prev_page": null
},
"message": null,
"error_code": 0
}
Update Chat
Rename an existing chat session.
Endpoint: PUT /api/v1/chats/{chat_id}
Path Parameters
| Parameter | Type | Description |
|---|---|---|
chat_id |
integer | The chat session ID |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | New chat session name (max 256 characters) |
external_user_id |
string | Conditional | Your system's user identifier. Required when you need to update a chat owned by a specific external user. For client-token authentication, this value is derived from the token instead of the request body. |
Example
curl -X PUT "https://api.codeer.ai/api/v1/chats/12345" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Renamed Support Session",
"external_user_id": "user_123"
}'
Response
{
"data": {
"id": 12345,
"name": "Renamed Support Session",
"meta": {
"external_user_id": "user_123",
"conversation_agent_id": "550e8400-e29b-41d4-a716-446655440000"
},
"external_user_id": "user_123",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:40:00Z"
},
"message": null,
"error_code": 0
}
Get Chat Messages
Retrieve the message history for a specific chat.
Endpoint: GET /api/v1/chats/{chat_id}/messages
Path Parameters
| Parameter | Type | Description |
|---|---|---|
chat_id |
integer | The chat session ID |
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
integer | 50 | Results per page |
offset |
integer | 0 | Number of results to skip |
include_tool_tags |
boolean | false |
Whether to keep <tool ...>...</tool> blocks in assistant messages. When false, tool blocks are removed from assistant content. |
external_user_id |
string | - | Your system's user identifier. Optional for API key authentication. For client-token authentication, this value is derived from the token instead of this query parameter. Can also be passed via x-external-user-id header for API key requests. |
Example
curl -X GET "https://api.codeer.ai/api/v1/chats/12345/messages?external_user_id=user_123" \
-H "x-api-key: YOUR_API_KEY"
Response
{
"data": [
{
"id": 1001,
"role": "user",
"group_id": "group_abc",
"content": "Hello, I need help with my order",
"meta": {},
"attached_files": [],
"feedback_counts": {}
},
{
"id": 1002,
"role": "assistant",
"group_id": "group_abc",
"content": "Hello! I'd be happy to help you with your order. Could you please provide your order number?",
"meta": {
"reasoning_steps": [...],
"token_usage": {
"total_prompt_tokens": 150,
"total_completion_tokens": 45,
"total_tokens": 195,
"total_calls": 1
}
},
"attached_files": [],
"feedback_counts": {
"sys_helpful": 1
}
}
],
"pagination": { ... },
"message": null,
"error_code": 0
}
Assistant Tool Block Visibility
include_tool_tags=false(default) removes<tool ...>...</tool>blocks from assistant messages in this endpoint.- Set
include_tool_tags=trueif your client needs the raw assistant tool blocks.
Send Message
Send a message to a chat and receive the agent's response. Supports both streaming (SSE) and non-streaming modes.
Endpoint: POST /api/v1/chats/{chat_id}/messages
Path Parameters
| Parameter | Type | Description |
|---|---|---|
chat_id |
integer | The chat session ID |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
message |
string | Yes | The user's message |
stream |
boolean | No | Enable SSE streaming (default: true) |
include_tool_tags |
boolean | No | Keep <tool ...>...</tool> blocks in non-stream data and SSE delta/completed text (default: false) |
agent_id |
UUID | Yes | The agent ID (must match chat's agent) |
attached_file_uuids |
array | No | UUIDs of uploaded files to attach |
resume_form_request_id |
string | No | Resume the last user turn after a form request is submitted or rejected |
external_user_id |
string | Conditional | Your system's user identifier. Required if workspace has whitelist mode enabled. |
Possible Error Responses
404 Not Foundwith "Agent not found" - The agent_id doesn't exist in this workspace404 Not Foundwith "Agent version not found" - The agent exists but has no published version404 Not Foundwith "Chat not found" - The chat_id doesn't exist400 Bad Requestwith "Agent mismatch" - The agent_id doesn't match the agent used to create the chat403 Forbiddenwith error code14103- Workspace has whitelist mode and external_user_id is missing or not whitelisted
Non-Streaming Example
curl -X POST "https://api.codeer.ai/api/v1/chats/12345/messages" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"message": "What are your business hours?",
"stream": false,
"agent_id": "550e8400-e29b-41d4-a716-446655440000"
}'
Non-Streaming Response
{
"data": "Our business hours are Monday to Friday, 9 AM to 6 PM EST. We're closed on weekends and major holidays. Is there anything specific you'd like to know about our availability?",
"structured_message": {
"final_text": "Our business hours are Monday to Friday, 9 AM to 6 PM EST. We're closed on weekends and major holidays. Is there anything specific you'd like to know about our availability?",
"conversation_group_id": "group_abc",
"user_conversation_id": 1001,
"assistant_conversation_id": 1002
},
"message": null,
"error_code": 0
}
Non-Streaming Response Shape
dataremains the plain text response for backward compatibility.structured_messageincludes IDs you can use without making an extra list-messages request.
Streaming Example
curl -N -X POST "https://api.codeer.ai/api/v1/chats/12345/messages" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-d '{
"message": "What are your business hours?",
"stream": true,
"agent_id": "550e8400-e29b-41d4-a716-446655440000"
}'
For detailed information on streaming responses, see SSE Streaming.
Tool Tag Visibility Rollout
- External API callers get
<tool>blocks hidden by default (include_tool_tagsomitted orfalse). - Internal clients that need tool blocks must explicitly pass
include_tool_tags=true. - The same flag applies to
POST /chats/{chat_id}/messages,POST /chats/{chat_id}/regenerate, andGET /chats/{chat_id}/messages.
Regenerate Message
Regenerate a conversation turn by reprocessing the original user message in a group.
Endpoint: POST /api/v1/chats/{chat_id}/regenerate
Path Parameters
| Parameter | Type | Description |
|---|---|---|
chat_id |
integer | The chat session ID |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
conversation_group_id |
string | Yes | Target conversation group ID to regenerate |
stream |
boolean | No | Enable SSE streaming (default: true) |
include_tool_tags |
boolean | No | Keep <tool ...>...</tool> blocks in non-stream data and SSE delta/completed text (default: false) |
external_user_id |
string | Conditional | Your system's user identifier. Required if workspace has whitelist mode enabled. |
Non-Streaming Example
curl -X POST "https://api.codeer.ai/api/v1/chats/12345/regenerate" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"conversation_group_id": "group_abc",
"stream": false
}'
Non-Streaming Response
{
"data": "Our business hours are Monday to Friday, 9 AM to 6 PM EST.",
"structured_message": {
"final_text": "Our business hours are Monday to Friday, 9 AM to 6 PM EST.",
"conversation_group_id": "group_abc",
"user_conversation_id": 1001,
"assistant_conversation_id": 1002
},
"message": null,
"error_code": 0
}
Streaming Example
curl -N -X POST "https://api.codeer.ai/api/v1/chats/12345/regenerate" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-d '{
"conversation_group_id": "group_abc",
"stream": true
}'
For detailed information on streaming responses, see SSE Streaming.
Submit or Reject Form Request
Submit a pending form request or mark it as rejected.
Endpoint: POST /api/v1/chats/{chat_id}/form-requests/{form_request_id}/submit
Path Parameters
| Parameter | Type | Description |
|---|---|---|
chat_id |
integer | The chat session ID |
form_request_id |
UUID | The pending form request ID |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
conversation_group_id |
string | Yes | The conversation group that opened the form request |
rejected |
boolean | No | Set true to reject the form request instead of submitting data |
submission |
object | Conditional | Required when rejected=false; must be empty when rejected=true |
external_user_id |
string | Conditional | Your system's user identifier. Required if workspace has whitelist mode enabled. |
Submit Example
curl -X POST "https://api.codeer.ai/api/v1/chats/12345/form-requests/form-uuid-here/submit" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"conversation_group_id": "group_abc",
"rejected": false,
"submission": {
"email": "user@example.com"
},
"external_user_id": "user_123"
}'
Reject Example
curl -X POST "https://api.codeer.ai/api/v1/chats/12345/form-requests/form-uuid-here/submit" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"conversation_group_id": "group_abc",
"rejected": true,
"submission": null,
"external_user_id": "user_123"
}'
Response
{
"data": null,
"message": null,
"error_code": 0
}
Continuing After Form Submission
If you want the agent to continue from the original user turn after a form request is submitted or rejected, call POST /api/v1/chats/{chat_id}/messages and pass the same form_request_id in resume_form_request_id.
Possible Error Responses
404 Not Found-form_request_iddoes not exist in this chat400 Bad Request-conversation_group_iddoes not match, or the form request is no longer pending
Upload File
Upload a file to attach to chat messages.
Endpoint: POST /api/v1/chats/upload-file
Constraints
| Constraint | Value |
|---|---|
| Maximum file size | 50 MB |
| Allowed MIME types | application/pdf, text/*, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/vnd.openxmlformats-officedocument.presentationml.presentation, image/jpeg, image/png, image/gif, image/webp, text/html |
| Allowed extensions | .pdf, .txt, .md, .csv, .docx, .doc, .pptx, .jpeg, .jpg, .png, .gif, .webp, .html |
Request
Use multipart/form-data encoding:
| Field | Type | Required | Description |
|---|---|---|---|
file |
binary | Yes | The file to upload |
data |
JSON string | No | JSON object with scope (persistent or ephemeral, default: persistent) and optional external_user_id |
For API key requests, include external_user_id in data when you want to associate the upload with a specific external user. For client-token requests, external_user_id is derived from the token, so you do not need to send it.
Example
curl -X POST "https://api.codeer.ai/api/v1/chats/upload-file" \
-H "x-api-key: YOUR_API_KEY" \
-F "file=@document.pdf" \
-F 'data={"scope":"persistent","external_user_id":"user_123"}'
Response
{
"data": {
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"original_name": "document.pdf",
"content_type": "application/pdf",
"size": 102400,
"file_url": "https://storage.codeer.ai/files/...",
"scope": "persistent"
},
"message": null,
"error_code": 0
}
Error Response
When validation fails, the response includes an error_msg field in the data:
{
"data": {
"original_name": "large-file.pdf",
"content_type": "application/pdf",
"size": 104857600,
"scope": "persistent",
"error_msg": "File size check failed (max size: 50 MB)"
},
"message": "File size check failed (max size: 50 MB)",
"error_code": 10006
}
Common validation errors:
"File size check failed (max size: 50 MB)"- File exceeds 50 MB limit"Unsupported content type: {type}"- MIME type not in allowed list"Unsupported file extension: {ext}"- Extension not in allowed list"File name is missing"- No filename provided"File is empty (size must be greater than 0 bytes)"- Empty file
Using Uploaded Files
After uploading, include the file UUID when sending a message:
curl -X POST "https://api.codeer.ai/api/v1/chats/12345/messages" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"message": "Please analyze this document",
"stream": true,
"agent_id": "550e8400-e29b-41d4-a716-446655440000",
"attached_file_uuids": ["a1b2c3d4-e5f6-7890-abcd-ef1234567890"]
}'
Create Message Feedback
Submit feedback on an assistant's response.
Endpoint: POST /api/v1/chats/{chat_id}/messages/{message_id}/feedbacks
Path Parameters
| Parameter | Type | Description |
|---|---|---|
chat_id |
integer | The chat session ID |
message_id |
integer | The message ID to provide feedback on |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
external_user_id |
string | Yes | Your system's user identifier |
type |
string | Yes | Feedback type: sys_helpful or sys_improve |
content |
string | No | Additional feedback text (only for sys_improve type, max 500 characters) |
Example
curl -X POST "https://api.codeer.ai/api/v1/chats/12345/messages/1002/feedbacks" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"external_user_id": "user_123",
"type": "sys_helpful"
}'
Response
{
"message": "Feedback created",
"error_code": 0
}
Code Examples
Python
import requests
API_KEY = "your-api-key"
BASE_URL = "https://api.codeer.ai/api/v1"
headers = {
"x-api-key": API_KEY,
"Content-Type": "application/json"
}
# Create a chat
chat_response = requests.post(
f"{BASE_URL}/chats",
headers=headers,
json={
"name": "API Test",
"agent_id": "your-agent-id",
"external_user_id": "user_123"
}
)
chat_id = chat_response.json()["data"]["id"]
# Send a message (non-streaming)
message_response = requests.post(
f"{BASE_URL}/chats/{chat_id}/messages",
headers=headers,
json={
"message": "Hello!",
"stream": False,
"agent_id": "your-agent-id"
}
)
print(message_response.json()["data"])
JavaScript
const API_KEY = 'your-api-key';
const BASE_URL = 'https://api.codeer.ai/api/v1';
const headers = {
'x-api-key': API_KEY,
'Content-Type': 'application/json'
};
// Create a chat
const chatResponse = await fetch(`${BASE_URL}/chats`, {
method: 'POST',
headers,
body: JSON.stringify({
name: 'API Test',
agent_id: 'your-agent-id',
external_user_id: 'user_123'
})
});
const { data: chat } = await chatResponse.json();
// Send a message (non-streaming)
const messageResponse = await fetch(`${BASE_URL}/chats/${chat.id}/messages`, {
method: 'POST',
headers,
body: JSON.stringify({
message: 'Hello!',
stream: false,
agent_id: 'your-agent-id'
})
});
const { data: reply } = await messageResponse.json();
console.log(reply);
For more examples including streaming implementations, see the official examples repository.