ChatKomodo Docs Home Sign in

API reference · Account

Analytics & usage

Today's counters

GET/v1/stats

Counters for the dashboard home: devices, messages since midnight (server time), running blasts and active auto-reply rules. Scoped to the tenant.

Responses

  • 200Counters
    Response fields
    • sessions_totalintegerrequired
      Devices of the tenant
    • sessions_connectedintegerrequired
      Devices currently connected
    • messages_sent_todayintegerrequired
      Outbound messages with status sent, delivered or read
    • messages_received_todayintegerrequired
    • messages_failed_todayintegerrequired
    • blasts_runningintegerrequired
    • auto_reply_activeintegerrequired
      Active auto-reply rules
  • 401Missing, invalid or expired credentials
Request
curl "https://api.chatkomodo.com/v1/stats" \
  -H "Authorization: Bearer $CHATKOMODO_API_KEY"
const res = await fetch('https://api.chatkomodo.com/v1/stats', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.code}: ${data.error}`);
console.log(data);
import os
import requests

res = requests.get(
    "https://api.chatkomodo.com/v1/stats",
    headers={
        "Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
    },
    timeout=30,
)
res.raise_for_status()
print(res.json())
<?php
require 'vendor/autoload.php';

$client = new GuzzleHttp\Client();
$res = $client->request('GET', 'https://api.chatkomodo.com/v1/stats', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
    ],
]);

print_r(json_decode((string) $res->getBody(), true));
Response 200
{
  "sessions_total": 12,
  "sessions_connected": 1,
  "messages_sent_today": 12,
  "messages_received_today": 1,
  "messages_failed_today": 1,
  "blasts_running": 1,
  "auto_reply_active": 1
}

Plan usage this month

GET/v1/usage

Messages sent and devices used against the plan limits for the current month (UTC), plus what the month would cost in the tenant's billing currency (minor units): plan price and overage beyond the quota.

Responses

  • 200Usage
    Response fields
    • periodstringrequired
      YYYY-MM (UTC)
    • planstring | nullrequired
      Plan name, or null when the tenant has no plan
    • sessionsintegerrequired
      Devices of the tenant
    • max_sessionsinteger | nullrequired
      Device limit of the plan
    • messages_usedintegerrequired
      Messages sent this month
    • messages_quotaintegerrequired
      Monthly message quota; 0 = unlimited
    • messages_remaininginteger | nullrequired
      Quota minus used (never negative); null when unlimited
    • send_per_minuteintegerrequired
      Requests per minute the plan allows on POST …messages…, per API key
    • billingobject | nullrequired
      null when the tenant has no plan or the plan has no price
    • billing.currencystringrequired
      ISO 4217 code
    • billing.plan_minorintegerrequired
      Plan price in minor units of currency
    • billing.overage_messagesintegerrequired
      Messages beyond the quota
    • billing.overage_minorintegerrequired
      Overage charge in minor units
    • billing.amount_due_minorintegerrequired
      plan_minor + overage_minor
  • 401Missing, invalid or expired credentials
Request
curl "https://api.chatkomodo.com/v1/usage" \
  -H "Authorization: Bearer $CHATKOMODO_API_KEY"
const res = await fetch('https://api.chatkomodo.com/v1/usage', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.code}: ${data.error}`);
console.log(data);
import os
import requests

res = requests.get(
    "https://api.chatkomodo.com/v1/usage",
    headers={
        "Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
    },
    timeout=30,
)
res.raise_for_status()
print(res.json())
<?php
require 'vendor/autoload.php';

$client = new GuzzleHttp\Client();
$res = $client->request('GET', 'https://api.chatkomodo.com/v1/usage', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
    ],
]);

print_r(json_decode((string) $res->getBody(), true));
Response 200
{
  "period": "string",
  "plan": "string",
  "sessions": 1,
  "max_sessions": 1,
  "messages_used": 12,
  "messages_quota": 1,
  "messages_remaining": 1,
  "send_per_minute": 1,
  "billing": {
    "currency": "IDR",
    "plan_minor": 1,
    "overage_messages": 1,
    "overage_minor": 1,
    "amount_due_minor": 150000
  }
}

Message analytics for 7, 30 or 90 days

GET/v1/analytics

Message counts for the last N days (including today), a per-day series, an inbound heatmap (weekday x hour), the 10 busiest chats and the average time to reply in 1:1 chats. Day boundaries follow the tenant's business timezone. The result is computed at most once a minute per tenant and window (later calls within the minute get the same answer).

Query parameters

  • daysstring
    Window length in days
    One of: 7, 30, 90Default: "7"

Responses

  • 200Analytics
    Response fields
    • daysintegerrequired
    • totalsobjectrequired
    • totals.sentintegerrequired
      Outbound messages with status sent, delivered or read
    • totals.receivedintegerrequired
    • totals.failedintegerrequired
    • totals.deliveredintegerrequired
      Outbound messages delivered or read
    • totals.readintegerrequired
      Outbound messages read
    • dailyarray of objectrequired
      One entry per day, oldest first
    • daily[].datestringrequired
      YYYY-MM-DD in the business timezone
    • daily[].sentintegerrequired
    • daily[].receivedintegerrequired
    • daily[].failedintegerrequired
    • heatmaparray of array of integerrequired
      Inbound messages: 7 rows (weekday, 0 = Sunday) of 24 columns (hour of day, business timezone)
    • top_chatsarray of objectrequired
      Up to 10 chats by message count
    • top_chats[].chat_idstringrequired
    • top_chats[].countintegerrequired
    • avg_response_msinteger | nullrequired
      Average time from a customer's message to the next reply in 1:1 chats, or null when there is no data
  • 400days is not 7, 30 or 90 (VALIDATION_FAILED)
  • 401Missing, invalid or expired credentials
Request
curl "https://api.chatkomodo.com/v1/analytics" \
  -H "Authorization: Bearer $CHATKOMODO_API_KEY"
const res = await fetch('https://api.chatkomodo.com/v1/analytics', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.code}: ${data.error}`);
console.log(data);
import os
import requests

res = requests.get(
    "https://api.chatkomodo.com/v1/analytics",
    headers={
        "Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
    },
    timeout=30,
)
res.raise_for_status()
print(res.json())
<?php
require 'vendor/autoload.php';

$client = new GuzzleHttp\Client();
$res = $client->request('GET', 'https://api.chatkomodo.com/v1/analytics', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
    ],
]);

print_r(json_decode((string) $res->getBody(), true));
Response 200
{
  "days": 1,
  "totals": {
    "sent": 12,
    "received": 1,
    "failed": 1,
    "delivered": 1,
    "read": 1
  },
  "daily": [
    {
      "date": "string",
      "sent": 12,
      "received": 1,
      "failed": 1
    }
  ],
  "heatmap": [
    [
      1
    ]
  ],
  "top_chats": [
    {
      "chat_id": "+447700900123",
      "count": 12
    }
  ],
  "avg_response_ms": 1767225600000
}

Customer-satisfaction results

GET/v1/csat/results

Ratings (1-5) collected by the satisfaction survey over the last N days: count, average, distribution and the 50 most recent ratings.

Query parameters

  • daysinteger
    Window in days; values outside 1-365 are clamped
    Default: 30From 1 to 365

Responses

  • 200Results
    Response fields
    • countintegerrequired
      Ratings received
    • avgnumberrequired
      Average rating, rounded to 2 decimals; 0 when there are none
    • distributionobjectrequired
      Ratings per score: keys 1 to 5
    • recentarray of objectrequired
    • recent[].session_idstringrequired
    • recent[].chat_idstringrequired
    • recent[].ratingintegerrequired
    • recent[].created_atintegerrequired
      When the customer answered
  • 401Missing, invalid or expired credentials
Request
curl "https://api.chatkomodo.com/v1/csat/results" \
  -H "Authorization: Bearer $CHATKOMODO_API_KEY"
const res = await fetch('https://api.chatkomodo.com/v1/csat/results', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.code}: ${data.error}`);
console.log(data);
import os
import requests

res = requests.get(
    "https://api.chatkomodo.com/v1/csat/results",
    headers={
        "Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
    },
    timeout=30,
)
res.raise_for_status()
print(res.json())
<?php
require 'vendor/autoload.php';

$client = new GuzzleHttp\Client();
$res = $client->request('GET', 'https://api.chatkomodo.com/v1/csat/results', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
    ],
]);

print_r(json_decode((string) $res->getBody(), true));
Response 200
{
  "count": 12,
  "avg": 0.5,
  "distribution": {},
  "recent": [
    {
      "session_id": "YOUR_DEVICE_ID",
      "chat_id": "+447700900123",
      "rating": 1,
      "created_at": 1767225600000
    }
  ]
}