Authentication
All API endpoints require a Bearer token. API keys are provisioned per workspace through the admin panel.
API Key Format
All API keys start with ctl_ followed by a random hex string.
Authorization: Bearer ctl_your_api_key_here
Getting your API key
- Open the admin panel:
http://localhost:8050/admin - Navigate to the API Keys tab
- Click Generate New Key — shown only once, copy it immediately
/api/v1/send
Send a WhatsApp text or media message. All sends route through the mimicry gate (time gate + hourly cap).
Returns 403 if blocked by quiet hours or cap.
Request Body
{
"chatId": "Alice", // Contact name or JID (e.g. "972501234567@c.us")
"session": "my_session", // WAHA session name
"text": "Hello from AI!", // Message text (required for text type)
"mediaUrl": "https://...", // Optional: media URL for image/video/file
"type": "image" // Optional: "image" | "video" | "file" | "voice"
}
Example
curl -X POST http://localhost:8050/api/v1/send \
-H "Authorization: Bearer ctl_your_key" \
-H "Content-Type: application/json" \
-d '{
"chatId": "972501234567@c.us",
"session": "my_session",
"text": "Hello from Chatlytics!"
}'
Response
{ "ok": true, "waha": { "id": "true_972501234567@c.us_ABCDEF123" } }
/api/v1/messages
Read recent messages from a WhatsApp chat.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| chatId | string | yes | Chat JID to read from |
| session | string | yes | WAHA session name |
| limit | integer | no | Max messages to return (default: 20, max: 100) |
curl "http://localhost:8050/api/v1/messages?chatId=972501234567@c.us&session=my_session&limit=10" \
-H "Authorization: Bearer ctl_your_key"
/api/v1/search
Search contacts and groups in the WhatsApp directory by name or JID.
curl "http://localhost:8050/api/v1/search?q=Alice&limit=10" \
-H "Authorization: Bearer ctl_your_key"
{
"contacts": [
{ "jid": "972501234567@c.us", "name": "Alice Smith", "phone": "972501234567" }
],
"groups": [
{ "jid": "120363421825201386@g.us", "name": "Team Chat" }
]
}
/api/v1/directory
Paginated listing of contacts, groups, and newsletters. Supports filtering and search.
curl "http://localhost:8050/api/v1/directory?type=group&limit=50&offset=0" \
-H "Authorization: Bearer ctl_your_key"
{
"items": [
{ "jid": "120363421825201386@g.us", "name": "Team Chat", "type": "group" },
{ "jid": "972501234567@c.us", "name": "Alice Smith", "type": "contact" }
],
"total": 42,
"limit": 50,
"offset": 0
}
/api/v1/sessions
List all WAHA sessions with their health status and connection state.
curl "http://localhost:8050/api/v1/sessions" \
-H "Authorization: Bearer ctl_your_key"
# Response:
{
"sessions": [
{
"session": "my_session",
"name": "My Bot",
"status": "WORKING",
"webhook_registered": true
}
]
}
/api/v1/status
Check current mimicry gate state — time gate open/closed and hourly cap usage. Read-only; never consumes quota.
curl "http://localhost:8050/api/v1/status" \
-H "Authorization: Bearer ctl_your_key"
# Response:
{
"session": "my_session",
"hourlyCapUsed": 12,
"hourlyCapLimit": 30,
"gateOpen": true
}
MCP Server
Chatlytics exposes a Model Context Protocol server with 10 tools. Connect any MCP-compatible client (Claude Desktop, Cursor, Continue.dev) using the config snippets below.
Claude Desktop
{
"mcpServers": {
"chatlytics": {
"command": "npx",
"args": ["-y", "chatlytics", "mcp"],
"env": {
"CHATLYTICS_URL": "http://localhost:8050",
"CHATLYTICS_API_KEY": "ctl_your_key_here"
}
}
}
}
Cursor
{
"mcpServers": {
"chatlytics": {
"command": "npx",
"args": ["-y", "chatlytics", "mcp"],
"env": {
"CHATLYTICS_URL": "http://localhost:8050",
"CHATLYTICS_API_KEY": "ctl_your_key_here"
}
}
}
}
Continue.dev
{
"experimental": {
"modelContextProtocolServers": [
{
"transport": {
"type": "stdio",
"command": "npx",
"args": ["-y", "chatlytics", "mcp"],
"env": {
"CHATLYTICS_URL": "http://localhost:8050",
"CHATLYTICS_API_KEY": "ctl_your_key_here"
}
}
}
]
}
}
HTTP Transport (Streamable)
For clients that support HTTP MCP transport directly:
POST http://localhost:8050/mcp
Authorization: Bearer ctl_your_key_here
Content-Type: application/json
Available MCP Tools
| Tool | Description |
|---|---|
| send_message | Send a WhatsApp text message through the mimicry gate |
| send_media | Send image, video, file, or voice via public URL |
| read_messages | Read recent messages from a chat |
| search | Search contacts and groups by name or JID |
| get_directory | List contacts, groups, or newsletters with pagination |
| get_sessions | List all WAHA sessions and their health status |
| get_status | Check mimicry gate state (time gate + hourly cap) |
| update_settings | Update plugin configuration (channels.waha.* paths) |
| get_group_info | Get group metadata including participant list |
| manage_group | Group operations: add/remove participants, rename, set description |
CLI Tool
Use Chatlytics from the command line via npx chatlytics — no install required.
Environment Variables
export CHATLYTICS_URL=http://localhost:8050
export CHATLYTICS_API_KEY=ctl_your_key_here
Commands
npx chatlytics send "Hello!" --to "Alice" --session my_session
npx chatlytics search "Team" --limit 20
npx chatlytics status
npx chatlytics read --chat "972501234567@c.us" --session my_session --limit 10
Webhooks
Receive incoming WhatsApp messages and events via HTTP callbacks. Chatlytics signs each request with HMAC-SHA256 using your API key as the secret.
Configure a callback URL
Set channels.waha.webhookSubscriptions in config:
{
"channels": {
"waha": {
"webhookSubscriptions": [
{
"url": "https://your-server.com/webhook",
"events": ["message", "message.reaction"]
}
]
}
}
}
Verify HMAC Signature (Node.js)
import crypto from "crypto";
function verifyWebhookSignature(req, apiKey) {
const sig = req.headers["x-chatlytics-signature"];
if (!sig) return false;
const body = JSON.stringify(req.body);
const expected = crypto
.createHmac("sha256", apiKey)
.update(body)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(sig),
Buffer.from(`sha256=${expected}`)
);
}
// Express usage:
app.post("/webhook", express.json(), (req, res) => {
if (!verifyWebhookSignature(req, process.env.CHATLYTICS_API_KEY)) {
return res.status(401).send("Unauthorized");
}
const event = req.body;
console.log("Received:", event.type, event.payload?.chatId);
res.sendStatus(200);
});
Retry behavior
- Failed deliveries (non-2xx) are retried up to 3 times with exponential backoff
- Circuit breaker opens after 5 consecutive failures — pauses delivery for 60 seconds
- Each event includes a unique
idfield for deduplication
Configuration
Key configuration fields for the mimicry engine and policy controls.
{
"channels": {
"waha": {
"apiUrl": "http://localhost:3004",
"apiKey": "your_waha_api_key",
// Mimicry gate — time-of-day restrictions
"sendGate": {
"enabled": true,
"startHour": 8, // 8 AM
"endHour": 22, // 10 PM
"timezone": "Asia/Jerusalem",
"onBlock": "reject" // "reject" | "queue"
},
// Hourly send cap
"hourlyCap": {
"enabled": true,
"limits": {
"new": 5, // New sessions — conservative
"growing": 15, // Growing sessions
"stable": 30, // Established sessions
"trusted": 60 // Long-standing accounts
}
}
}
}
}
Updating config via API
Use the update_settings MCP tool
or the admin panel Settings tab. Changes take effect immediately without restart.