Chatlytics
GitHub

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.

ctl_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4
HTTP Header
Authorization: Bearer ctl_your_api_key_here

Getting your API key

  1. Open the admin panel: http://localhost:8050/admin
  2. Navigate to the API Keys tab
  3. Click Generate New Key — shown only once, copy it immediately
POST

/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

application/json
{
  "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
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

200 OK
{ "ok": true, "waha": { "id": "true_972501234567@c.us_ABCDEF123" } }
GET

/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
curl "http://localhost:8050/api/v1/messages?chatId=972501234567@c.us&session=my_session&limit=10" \
  -H "Authorization: Bearer ctl_your_key"
GET

/api/v1/directory

Paginated listing of contacts, groups, and newsletters. Supports filtering and search.

curl — list all groups
curl "http://localhost:8050/api/v1/directory?type=group&limit=50&offset=0" \
  -H "Authorization: Bearer ctl_your_key"
200 Response
{
  "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
}
GET

/api/v1/sessions

List all WAHA sessions with their health status and connection state.

curl
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
    }
  ]
}
GET

/api/v1/status

Check current mimicry gate state — time gate open/closed and hourly cap usage. Read-only; never consumes quota.

curl
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

~/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "chatlytics": {
      "command": "npx",
      "args": ["-y", "chatlytics", "mcp"],
      "env": {
        "CHATLYTICS_URL": "http://localhost:8050",
        "CHATLYTICS_API_KEY": "ctl_your_key_here"
      }
    }
  }
}

Cursor

~/.cursor/mcp.json
{
  "mcpServers": {
    "chatlytics": {
      "command": "npx",
      "args": ["-y", "chatlytics", "mcp"],
      "env": {
        "CHATLYTICS_URL": "http://localhost:8050",
        "CHATLYTICS_API_KEY": "ctl_your_key_here"
      }
    }
  }
}

Continue.dev

~/.continue/config.json
{
  "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:

HTTP MCP endpoint
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

.env or shell export
export CHATLYTICS_URL=http://localhost:8050
export CHATLYTICS_API_KEY=ctl_your_key_here

Commands

send — send a message
npx chatlytics send "Hello!" --to "Alice" --session my_session
search — find contacts or groups
npx chatlytics search "Team" --limit 20
status — check gate and cap
npx chatlytics status
read — read messages from chat
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:

Configuration snippet
{
  "channels": {
    "waha": {
      "webhookSubscriptions": [
        {
          "url": "https://your-server.com/webhook",
          "events": ["message", "message.reaction"]
        }
      ]
    }
  }
}

Verify HMAC Signature (Node.js)

Node.js — signature verification
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 id field for deduplication

Configuration

Key configuration fields for the mimicry engine and policy controls.

channels.waha config (excerpt)
{
  "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.