Chatmount API
Integrate your Chatmount chatbot into any application. Send messages, receive AI-powered responses with source citations, and build custom chat experiences — all through a simple REST API.
The API uses the same RAG pipeline as the embedded widget — your chatbot's training data, system prompt, and behavior are identical across all channels.
Authentication
All API requests require an API key sent in the Authorization header. Keys are scoped to a single chatbot — one key can only query the chatbot it was created for.
Authorization: Bearer cm_live_YOUR_API_KEYGetting your API key
- Go to your chatbot dashboard
- Select a chatbot and navigate to the API tab
- Click Create API Key, give it a name, and copy the key
Keep your key secret
API keys carry full access to your chatbot. Never expose them in client-side code, public repositories, or browser requests. The API has no CORS headers — it is designed for server-to-server use only.
Key format
All keys start with cm_live_ followed by 32 alphanumeric characters. Keys are shown only once at creation — store them securely. You can rotate or revoke keys at any time from the dashboard.
Availability
API access is available on Plus and Enterprise plans. Free and Go plans do not include API key support. View pricing
Quick Start
Send your first message in under a minute. Replace cm_live_YOUR_API_KEY with your actual key.
curl -X POST https://services.chatmount.co/v1/chat \
-H "Authorization: Bearer cm_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"message": "What are your business hours?",
"include_sources": true
}'{
"message": "Our business hours are Monday through Friday, 9am to 5pm EST.",
"sources": [
{
"url": "https://example.com/about",
"title": "About Us"
}
],
"usage": {
"credits_used": 1,
"credits_remaining": 99
}
}API Reference
https://services.chatmount.co/v1/chatSend a message to your chatbot and receive an AI-generated response based on your training data. The chatbot ID is determined by your API key — each key is scoped to a single chatbot.
Request body
| Field | Type | Description |
|---|---|---|
| message | string | The user's message. Must be 1-2000 characters. |
| stream | boolean | Enable Server-Sent Events streaming. Default: false |
| session_id | string | Reuse a session ID for multi-turn conversations. The bot remembers prior messages within the same session. |
| include_sources | boolean | Include source document URLs in the response. Default: true |
Response body
| Field | Type | Description |
|---|---|---|
| message | string | The chatbot's response message. |
| sources | array | Up to 3 source documents used to generate the response. Each has url and title fields. |
| usage | object | Credit consumption. credits_used is always 1. credits_remaining shows your monthly balance. |
Streaming
Set "stream": true to receive the response as Server-Sent Events (SSE). Tokens are sent as they are generated, giving your users a real-time typing experience.
Event format
data: {"type":"token","content":"Our"}
data: {"type":"token","content":" business"}
data: {"type":"token","content":" hours"}
data: {"type":"token","content":" are"}
data: {"type":"token","content":" Monday-Friday, 9am-5pm."}
data: {"type":"sources","sources":[{"url":"https://example.com/about","title":"About Us"}]}
data: {"type":"done"}Event types
| Type | Payload | Description |
|---|---|---|
| token | { content: string } | A chunk of the response text. Concatenate all token contents for the full message. |
| sources | { sources: array } | Source documents used for the response. Sent once, after all tokens. |
| done | {} | Stream complete. Close the connection. |
Streaming examples
curl -X POST https://services.chatmount.co/v1/chat \
-H "Authorization: Bearer cm_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
--no-buffer \
-d '{
"message": "What are your business hours?",
"stream": true
}'Sessions
Use the session_id parameter to maintain conversation context across multiple requests. The chatbot will remember prior messages within the same session, enabling natural multi-turn conversations.
If you don't provide a session ID, each request is treated as an independent conversation. Session IDs can be any string — use your own user or conversation identifiers.
# First message
curl -X POST https://services.chatmount.co/v1/chat \
-H "Authorization: Bearer cm_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"message": "What services do you offer?",
"session_id": "user-123-session-abc"
}'
# Follow-up (same session_id — bot remembers context)
curl -X POST https://services.chatmount.co/v1/chat \
-H "Authorization: Bearer cm_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"message": "Tell me more about the first one",
"session_id": "user-123-session-abc"
}'Rate Limits
Rate limits are enforced per API key. Each request consumes 1 credit from your monthly pool (shared with widget chat usage).
| Plan | Requests / min | Credits / month |
|---|---|---|
| Plus | 60 | 1,500 |
| Enterprise | 200 | Unlimited |
Rate limit headers
Every response includes headers to help you manage your request rate:
| Header | Description |
|---|---|
| X-RateLimit-Limit | Maximum requests allowed per minute for your key. |
| X-RateLimit-Remaining | Requests remaining in the current 60-second window. |
| X-RateLimit-Reset | Unix timestamp (seconds) when the rate limit window resets. |
Handling rate limits
- 1.Check
X-RateLimit-Remainingbefore each request to avoid hitting the limit. - 2.If you receive a 429 response, wait until
X-RateLimit-Resetbefore retrying. - 3.Implement exponential backoff for retries — start at 1 second, double on each attempt, cap at 30 seconds.
Error Handling
Errors return a JSON body with an error field describing the issue.
{
"error": "Message must be between 1 and 2000 characters"
}Error codes
| Code | Meaning |
|---|---|
| 400 | Invalid request — message missing, empty, or exceeds 2000 characters. |
| 401 | Invalid, revoked, or expired API key. |
| 403 | API key not authorized for this chatbot, or your IP is not in the key's allowlist. |
| 429 | Rate limit exceeded, daily message cap reached, or monthly credits depleted. |
| 503 | Service temporarily overloaded. |
Code Examples
Complete working examples in popular languages. All examples include error handling and can be copied directly into your project.
Python
import requests
import json
import os
API_KEY = os.environ.get("CHATMOUNT_API_KEY")
BASE_URL = "https://services.chatmount.co/v1/chat"
def chat(message, stream=False, session_id=None):
"""Send a message and return the response."""
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
payload = {
"message": message,
"stream": stream,
"include_sources": True,
}
if session_id:
payload["session_id"] = session_id
response = requests.post(BASE_URL, headers=headers, json=payload, stream=stream)
# Handle errors
if response.status_code == 429:
reset = response.headers.get("X-RateLimit-Reset")
print(f"Rate limited. Retry after timestamp: {reset}")
return None
response.raise_for_status()
if not stream:
return response.json()
# Streaming
full_response = ""
for line in response.iter_lines():
if line:
line = line.decode("utf-8")
if line.startswith("data: "):
event = json.loads(line[6:])
if event["type"] == "token":
full_response += event["content"]
print(event["content"], end="", flush=True)
elif event["type"] == "sources":
print("\n\nSources:")
for s in event["sources"]:
print(f" - {s['title']}: {s['url']}")
elif event["type"] == "done":
print()
return full_response
# Usage
reply = chat("What services do you offer?")
print(reply["message"])
# Streaming
chat("Tell me more", stream=True)
# Multi-turn conversation
chat("What services do you offer?", session_id="session-123")
chat("Tell me more about the first one", session_id="session-123")Node.js
const API_KEY = process.env.CHATMOUNT_API_KEY;
const BASE_URL = "https://services.chatmount.co/v1/chat";
async function chat(message, { stream = false, sessionId } = {}) {
const response = await fetch(BASE_URL, {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
message,
stream,
session_id: sessionId,
include_sources: true,
}),
});
// Handle errors
if (response.status === 429) {
const reset = response.headers.get("X-RateLimit-Reset");
console.error(`Rate limited. Retry after: ${reset}`);
return null;
}
if (!response.ok) {
const err = await response.json();
throw new Error(err.error || `HTTP ${response.status}`);
}
if (!stream) {
return response.json();
}
// Streaming
const reader = response.body.getReader();
const decoder = new TextDecoder();
let fullResponse = "";
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
for (const line of chunk.split("\n")) {
if (line.startsWith("data: ")) {
const event = JSON.parse(line.slice(6));
if (event.type === "token") {
fullResponse += event.content;
process.stdout.write(event.content);
} else if (event.type === "sources") {
console.log("\nSources:", event.sources);
}
}
}
}
return fullResponse;
}
// Usage
const reply = await chat("What services do you offer?");
console.log(reply.message);
// Streaming
await chat("Tell me more", { stream: true });
// Multi-turn conversation
await chat("What services do you offer?", { sessionId: "session-123" });
await chat("Tell me more about the first one", { sessionId: "session-123" });cURL
# Non-streaming request
curl -X POST https://services.chatmount.co/v1/chat \
-H "Authorization: Bearer $CHATMOUNT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"message": "What services do you offer?",
"include_sources": true
}'
# Streaming request
curl -X POST https://services.chatmount.co/v1/chat \
-H "Authorization: Bearer $CHATMOUNT_API_KEY" \
-H "Content-Type: application/json" \
--no-buffer \
-d '{
"message": "What services do you offer?",
"stream": true
}'
# With session ID (multi-turn)
curl -X POST https://services.chatmount.co/v1/chat \
-H "Authorization: Bearer $CHATMOUNT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"message": "Tell me more about the first one",
"session_id": "session-123"
}'