Developer

API Documentation

Version 1.0 | Base URL: https://api.chat.co

1. Overview

The Chat.co API allows you to programmatically integrate your chatbots into custom applications, websites, and workflows. With this API, you can create and manage conversations, send messages, receive AI-powered responses, and stream responses in real-time.

Looking for AI agent integrations? This page covers the direct HTTP API. If you want Claude Desktop, Cursor, or another MCP-compatible client to work with Chat.co, start with API vs MCP and MCP Agent Setup.

1.1 Key Features

FeatureDescription
RESTful APIStandard HTTP methods (GET, POST, DELETE)
Streaming SupportReal-time response streaming via SSE or plain text
Scoped API KeysKeys can be restricted to specific chatbots for security
Citation SupportAI responses include source citations when available
Document ContextAttach uploaded documents to enhance AI responses

1.2 Getting Started

To use the direct Chat.co API, you need to:

  • Create a Chat.co account and set up a chatbot
  • Generate an API key from your Settings page
  • Assign the API key to a specific chatbot
  • Use the API key in your application's requests

2. Authentication

Important: MCP uses a different onboarding flow than the direct API. Instead of manually creating a dashboard key and copying it into your client, MCP typically uses agent login with browser approval. See MCP Agent Setup.

2.1 Two kinds of key

Chat.co issues two key types, and choosing the wrong one is the most common security mistake teams make with this API.

sk_live_…

Secret key

Full-power server-side credential. Carries whatever scopes you grant it, up to and including creating and deleting bots. Never ship one to a browser, a mobile app, or anything a user can read.

pk_live_…

Publishable key

Browser-safe, bound to a single chatbot, and permanently locked to chat:read and chat:write — those scopes are forced at mint time and re-forced on every request. It can hold a conversation and nothing else.

Publishable keys are visible credentials. They are embedded in pages your visitors load, and their domain restriction is enforced from the Origin/Referer headers — which anything outside a browser can set freely. Treat a pk_live_ as public: fine for the embedded chat it was designed for, never a substitute for a secret key.

2.2 Scopes

Every secret key carries an explicit scope list. A request whose key lacks the required scope is rejected with 403, even if the key is otherwise valid and the chatbot is accessible — this is the single most common cause of a correct-looking request failing.

ScopeGrants
chat:readRead conversations and messages
chat:writeCreate conversations and send messages
bot:readRead chatbot details and configuration
bot:writeCreate, update and delete chatbots; change configuration
content:readRead Q&A pairs and text training
content:writeCreate, update and delete Q&A pairs and text training
crawl:readRead crawl jobs, crawled pages and document jobs
crawl:writeStart and cancel crawls; upload and delete documents
analytics:readRead analytics, leads, knowledge gaps and message allocation

A key created without an explicit scope list defaults to chat:read and chat:write only. Grant the narrowest set that does the job — a key that only reads analytics should not be able to delete a bot.

2.3 Authorization Header

Include your API key in the Authorization header of every request:

Authorization: Bearer sk_live_your_api_key_here

You can also send the key without the Bearer prefix:

Authorization: sk_live_your_api_key_here

2.4 Security Best Practices

Important: Never expose API keys in client-side code (JavaScript, mobile apps). Store keys in environment variables or secure vaults.

  • Use chatbot-scoped keys when possible to limit access
  • Set expiration dates for temporary integrations
  • Rotate keys periodically
  • Delete unused keys promptly
  • Never commit API keys to version control

3. API Key Management

These endpoints require JWT authentication (your user session from the dashboard), not API key authentication.

3.1 Generate API Key

Creates a new API key for your account.

POST /api-keys

Request Body

{
  "name": "My Integration Key",
  "expiresAt": "2026-12-31T23:59:59Z",
  "chatbotId": "507f1f77bcf86cd799439011"
}
FieldTypeRequiredDescription
namestringNoUser-friendly name (max 100 chars)
expiresAtISO 8601 dateNoExpiration date (must be in future)
chatbotIdstringNoChatbot ID to scope the key

Response (201 Created)

{
  "success": true,
  "message": "API key generated successfully...",
  "data": {
    "id": "507f1f77bcf86cd799439011",
    "key": "sk_live_abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx",
    "keyPrefix": "sk_live_abcd1234efgh5678...",
    "name": "My Integration Key",
    "expiresAt": "2026-12-31T23:59:59.000Z",
    "createdAt": "2025-11-10T12:00:00.000Z"
  }
}

Warning: The full key value is shown only once. Store it securely immediately.

3.2 List API Keys

GET /api-keys?page=1&limit=10

Returns a paginated list of your API keys (prefixes only, not full keys).

3.3 Delete API Key

DELETE /api-keys/:id

Soft-deletes an API key. The key will immediately become invalid.

4. Chat Endpoints

All Client API endpoints require API key authentication and are prefixed with /client/v1.

Important: Your API key must be associated with a chatbot. Keys without a chatbot assignment will receive a CHATBOT_ACCESS_DENIED error.

4.1 Get Chatbot Details

GET /client/v1/chatbot

Retrieves the chatbot configuration and appearance settings associated with your API key.

Response

{
  "success": true,
  "data": {
    "chatbot": {
      "id": "507f1f77bcf86cd799439011",
      "name": "Customer Support Bot",
      "isPublic": true,
      "appearance": {
        "title": "Support Assistant",
        "welcomeMessage": "Hello! How can I help you today?",
        "placeholderText": "Type your question...",
        "suggestions": [
          { "value": "What are your hours?" }
        ],
        "enableDocumentUpload": true,
        "showCitations": true
      },
      "createdAt": "2025-01-15T10:00:00.000Z"
    }
  }
}

4.2 List Conversations

GET /client/v1/conversations

Query Parameters

ParameterTypeDefaultDescription
pageinteger1Page number
limitinteger20Items per page (max 100)
sortBystringcreatedAtcreatedAt or updatedAt
sortOrderstringdescasc or desc
startDateISO 8601-Filter from this date
endDateISO 8601-Filter until this date

4.3 Create Conversation

POST /client/v1/conversations

Request Body

{
  "metadata": {
    "source": "mobile-app",
    "clientId": "user-12345"
  }
}

Response (201 Created)

{
  "success": true,
  "data": {
    "conversation": {
      "id": "507f1f77bcf86cd799439011",
      "chatbotId": "507f1f77bcf86cd799439012",
      "chatbot": {
        "id": "507f1f77bcf86cd799439012",
        "name": "Customer Support Bot"
      },
      "createdAt": "2025-11-10T10:00:00.000Z"
    }
  }
}

4.4 Get Conversation

GET /client/v1/conversations/:conversationId

Retrieves a conversation with all its messages.

4.5 Send Message (Non-Streaming)

POST /client/v1/conversations/:conversationId/messages

Request Body

{
  "message": "What are your business hours?",
  "documentIds": ["507f1f77bcf86cd799439015"]
}
FieldTypeRequiredDescription
messagestringYesMessage content (max 8,000 chars)
documentIdsarrayNoIDs of uploaded documents

Response

{
  "success": true,
  "data": {
    "userMessage": {
      "id": "507f1f77bcf86cd799439016",
      "content": "What are your business hours?",
      "isFromUser": true,
      "createdAt": "2025-11-10T10:16:00.000Z"
    },
    "botResponse": {
      "id": "507f1f77bcf86cd799439017",
      "content": "Our business hours are Monday through Friday, 9:00 AM to 5:00 PM EST.",
      "isFromUser": false,
      "createdAt": "2025-11-10T10:16:03.000Z",
      "citations": [
        {
          "title": "Contact Information",
          "url": "https://example.com/contact",
          "snippet": "Hours of operation: Mon-Fri 9AM-5PM EST"
        }
      ]
    }
  }
}

4.6 Send Message (Streaming)

POST /client/v1/conversations/:conversationId/messages/stream

Sends a message and receives the AI response as a real-time stream. See Section 6 for streaming details.

5. Management API

The endpoints in Section 4 are the chat surface: they let a key already bound to one chatbot hold conversations. The Management API is everything else — creating bots, loading knowledge into them, and reading what comes back out. These routes are addressed by chatbot ID, so a single secret key can operate across every bot it has access to.

Secret keys only. Every route below requires a scope beyond chat:*, so a publishable key cannot reach any of them.

5.1 Chatbots

MethodPathScopeDescription
GET/client/v1/chatbotsbot:readList every chatbot this key can reach
GET/client/v1/chatbots/:chatbotIdbot:readGet one chatbot
POST/client/v1/chatbotsbot:writeCreate a chatbot
PATCH/client/v1/chatbots/:chatbotIdbot:writeRename, or change visibility
DELETE/client/v1/chatbots/:chatbotIdbot:writeSoft-delete a chatbot

5.2 Configuration

Paths below are relative to /client/v1/chatbots/:chatbotId.

MethodPathScopeDescription
GET/configbot:readFull sanitized configuration — never includes provider API keys
PATCH/temperaturebot:writeSet response creativity
PATCH/text-promptbot:writeReplace the system instruction prompt
PATCH/appearancebot:writeWidget appearance, voice and citation settings
PATCH/domainbot:writeAllowed embed domains and per-domain rate limits
GET/whitelistbot:readRead email whitelist settings
POST/whitelist/emailsbot:writeAdd an email to the whitelist (private bots)
DELETE/whitelist/emailsbot:writeRemove an email from the whitelist
PATCH/whitelistbot:writeTurn whitelist enforcement on or off

5.3 Documents & crawling

Uploading is a three-step flow — presign, PUT the bytes straight to S3, then finalize. The file never transits the Chat.co API, which is what makes large uploads workable. Crawls pause after discovery so you choose which pages to keep.

MethodPathScopeDescription
GET/documentscrawl:readList uploaded document jobs
GET/documents/check-existingcrawl:readCheck whether a file name was already uploaded
POST/documents/presign-uploadcrawl:writeReserve storage, get a presigned S3 PUT URL
POST/documents/finalize-uploadcrawl:writeTurn a completed upload into a processing job
GET/documents/:jobIdcrawl:readProcessing status for one document
DELETE/documentscrawl:writeDelete document jobs
POST/crawl/jobscrawl:writeStart a crawl
GET/crawl/jobscrawl:readList crawl jobs
GET/crawl/jobs/:jobIdcrawl:readCrawl job status
POST/crawl/jobs/:jobId/cancelcrawl:writeCancel a running crawl
GET/crawl/jobs/:jobId/pagescrawl:readPages a crawl stored
GET/crawl/jobs/:jobId/pending-pagescrawl:readDiscovered pages awaiting selection
POST/crawl/jobs/:jobId/select-pagescrawl:writeChoose which discovered pages to index
POST/crawl/jobs/:jobId/cancel-selectioncrawl:writeDiscard the pending pages

5.4 Q&A and text training

MethodPathScopeDescription
GET/qnacontent:readList Q&A pairs
POST/qnacontent:writeCreate a Q&A pair
POST/qna/bulkcontent:writeCreate many Q&A pairs in one call
GET/qna/:qnaIdcontent:readGet one Q&A pair
PATCH/qna/:qnaIdcontent:writeUpdate a Q&A pair
DELETE/qna/:qnaIdcontent:writeDelete a Q&A pair
GET/text-training/statuscontent:readWhether text training content exists
PUT/text-trainingcontent:writeCreate or replace the text training body
DELETE/text-trainingcontent:writeRemove text training content

5.5 Analytics, leads & knowledge gaps

MethodPathScopeDescription
GET/client/v1/message-allocationanalytics:readRemaining message credits for the key owner
POST/client/v1/chatbots/:chatbotId/analyticsanalytics:readAnalytics for one chatbot
GET/client/v1/chatbots/:chatbotId/leadsanalytics:readLeads captured by one chatbot
GET/client/v1/chatbots/:chatbotId/knowledge-gapsanalytics:readQuestions the bot could not answer
POST/client/v1/chatbots/:chatbotId/knowledge-gaps/suggest-answeranalytics:readDraft an answer for a detected gap
POST/client/v1/chatbots/:chatbotId/knowledge-gaps/create-qnacontent:writePromote a gap straight into a Q&A pair

Driving these endpoints from an AI client — Claude Desktop, Claude Code, Cursor — is usually easier through MCP than through raw HTTP. The Chat.co MCP server wraps this same surface as tools. See MCP Agent Setup and API vs MCP.

6. Streaming Responses

The streaming endpoint supports two formats via the format query parameter.

6.1 Plain Text Format (Default)

Best for simple integrations and testing with tools like Postman.

[START:507f1f77bcf86cd799439016]
Our return policy allows you to return most items within 30 days of purchase.

1. Items must be in original condition
2. You'll need the original receipt

[COMPLETE]
{"botMessageId":"507f1f77bcf86cd799439017","citations":[...]}
MarkerDescription
[START:id]Stream started, includes user message ID
<content>Streamed response text (arrives incrementally)
[COMPLETE]Stream finished successfully
[ERROR]An error occurred during streaming

6.2 Server-Sent Events (SSE) Format

Best for JavaScript applications using the EventSource API. Use ?format=sse.

data: {"type":"start","userMessageId":"507f1f77bcf86cd799439016"}

data: {"type":"content","content":"Our return policy"}

data: {"type":"content","content":" allows you to return"}

data: {"type":"complete","botMessageId":"507f1f77bcf86cd799439017","citations":[]}
Event TypeFieldsDescription
startuserMessageIdStream started
contentcontentText chunk to append
completebotMessageId, citationsStream finished
errorerrorError message

7. Error Handling

7.1 Response Format

All API responses follow a consistent format:

Success Response

{
  "success": true,
  "data": { ... }
}

Error Response

{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable error description"
  }
}

7.2 Error Codes

CodeHTTP StatusDescription
INVALID_API_KEY401API key is missing, malformed, expired, or invalid
RATE_LIMIT_EXCEEDED401/429Too many failed attempts or message rate limit
CHATBOT_NOT_FOUND404Chatbot does not exist
CHATBOT_ACCESS_DENIED403API key not associated with chatbot
CHATBOT_FROZEN403Chatbot is frozen due to plan downgrade
CONVERSATION_NOT_FOUND404Conversation does not exist
CONVERSATION_ACCESS_DENIED403No access to this conversation
MESSAGE_LIMIT_EXCEEDED403Monthly message credit limit reached
INVALID_REQUEST400Request body validation failed
INTERNAL_ERROR500Unexpected server error

8. Rate Limiting

8.1 Authentication Rate Limits

To protect against brute-force attacks, authentication is rate-limited:

LimitValue
Failed attempts5 per IP address
Lockout duration15 minutes

8.2 Message Rate Limits

Message rate limits are based on your subscription plan. Exceeding your monthly message limit returns MESSAGE_LIMIT_EXCEEDED.

9. Code Examples

9.1 cURL Examples

Get Chatbot

curl -X GET "https://api.chat.co/client/v1/chatbot" \
  -H "Authorization: Bearer sk_live_your_api_key"

Create Conversation

curl -X POST "https://api.chat.co/client/v1/conversations" \
  -H "Authorization: Bearer sk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{}'

Send Message

curl -X POST "https://api.chat.co/client/v1/conversations/CONVERSATION_ID/messages" \
  -H "Authorization: Bearer sk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"message": "Hello, I need help"}'

Stream Message

curl -X POST "https://api.chat.co/client/v1/conversations/CONVERSATION_ID/messages/stream?format=plain" \
  -H "Authorization: Bearer sk_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"message": "Tell me about your products"}' \
  --no-buffer

9.2 Node.js Example

const axios = require('axios');

const API_KEY = 'sk_live_your_api_key';
const BASE_URL = 'https://api.chat.co/client/v1';

const client = axios.create({
  baseURL: BASE_URL,
  headers: {
    'Authorization': `Bearer ${API_KEY}`,
    'Content-Type': 'application/json'
  }
});

async function chat() {
  // 1. Create a new conversation
  const { data: convResponse } = await client.post('/conversations');
  const conversationId = convResponse.data.conversation.id;
  console.log('Created conversation:', conversationId);

  // 2. Send a message
  const { data: msgResponse } = await client.post(
    `/conversations/${conversationId}/messages`,
    { message: 'What services do you offer?' }
  );

  console.log('Bot response:', msgResponse.data.botResponse.content);
  console.log('Citations:', msgResponse.data.botResponse.citations);
}

chat();

9.3 Python Example

import requests

API_KEY = 'sk_live_your_api_key'
BASE_URL = 'https://api.chat.co/client/v1'

headers = {
    'Authorization': f'Bearer {API_KEY}',
    'Content-Type': 'application/json'
}

# Create conversation
response = requests.post(f'{BASE_URL}/conversations', headers=headers, json={})
conversation_id = response.json()['data']['conversation']['id']
print(f'Created conversation: {conversation_id}')

# Send message
response = requests.post(
    f'{BASE_URL}/conversations/{conversation_id}/messages',
    headers=headers,
    json={'message': 'What are your pricing plans?'}
)

result = response.json()
print(f"Bot: {result['data']['botResponse']['content']}")

9.4 Python Streaming Example

import requests

API_KEY = 'sk_live_your_api_key'
BASE_URL = 'https://api.chat.co/client/v1'

headers = {
    'Authorization': f'Bearer {API_KEY}',
    'Content-Type': 'application/json'
}

conversation_id = 'your_conversation_id'

# Stream response
response = requests.post(
    f'{BASE_URL}/conversations/{conversation_id}/messages/stream?format=plain',
    headers=headers,
    json={'message': 'Explain your features in detail'},
    stream=True
)

for chunk in response.iter_content(chunk_size=None, decode_unicode=True):
    if chunk:
        print(chunk, end='', flush=True)

Need Help?

If you have questions or need assistance with the API, our team is here to help.

Email: support@chat.co

© 2026 SA Cyber LLC d/b/a Chat.co. All rights reserved.