Skip to content

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=true if 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 Found with "Agent not found" - The agent_id doesn't exist in this workspace
  • 404 Not Found with "Agent version not found" - The agent exists but has no published version
  • 404 Not Found with "Chat not found" - The chat_id doesn't exist
  • 400 Bad Request with "Agent mismatch" - The agent_id doesn't match the agent used to create the chat
  • 403 Forbidden with error code 14103 - 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

  • data remains the plain text response for backward compatibility.
  • structured_message includes 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_tags omitted or false).
  • 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, and GET /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_id does not exist in this chat
  • 400 Bad Request - conversation_group_id does 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.