. Create an API key under API keys.Guide
Quickstart: send your first message
From zero to a delivered WhatsApp message in five steps.
1. Create an account and link a number
Sign up at chatkomodo.com with your WhatsApp number. In the dashboard open Devices → Connect a device and scan the QR code with the phone whose number should send: WhatsApp → Settings → Linked devices → Link a device. The number keeps working on the phone as usual.
Use a number that is already active on WhatsApp. A brand-new number is warmed up for its first day: it sends more slowly.
2. Create an API key
In the dashboard open API keys → Create key. The key is shown once: store it in your server's secrets (an environment variable such as CHATKOMODO_API_KEY), never in a website or mobile app.
export CHATKOMODO_API_KEY="paste-your-key-here"3. Find your device id
GET /v1/sessions lists your devices. Take the id of the one with "status": "connected".
curl "https://api.chatkomodo.com/v1/sessions" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY"const res = await fetch('https://api.chatkomodo.com/v1/sessions', {
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/sessions",
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/sessions', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"sessions": [
{
"id": "01JA5V6Q8M2H7G4K9P3T0R1S2X",
"status": "connected",
"phone_number": "447700900000",
"phone_display": "+44 7700 900000",
"wa_name": "Acme Dental"
}
]
}4. Send a message
Write the recipient in international format (+<country code><number>):
curl -X POST "https://api.chatkomodo.com/v1/sessions/YOUR_DEVICE_ID/messages" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"chat_id": "+447700900123",
"type": "text",
"body": "Hello from ChatKomodo 👋"
}'const res = await fetch('https://api.chatkomodo.com/v1/sessions/YOUR_DEVICE_ID/messages', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"chat_id": "+447700900123",
"type": "text",
"body": "Hello from ChatKomodo 👋"
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.code}: ${data.error}`);
console.log(data);import os
import requests
res = requests.post(
"https://api.chatkomodo.com/v1/sessions/YOUR_DEVICE_ID/messages",
headers={
"Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
},
json={
"chat_id": "+447700900123",
"type": "text",
"body": "Hello from ChatKomodo 👋",
},
timeout=30,
)
res.raise_for_status()
print(res.json())<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$res = $client->request('POST', 'https://api.chatkomodo.com/v1/sessions/YOUR_DEVICE_ID/messages', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
'json' => [
'chat_id' => '+447700900123',
'type' => 'text',
'body' => 'Hello from ChatKomodo 👋',
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"id": "01JA5W2B7C9D0E1F2G3H4J5K6M",
"status": "queued"
}Check where it is with GET /v1/sessions/{sessionId}/messages (queued → sent → delivered → read) — or let a webhook tell you.
5. Receive replies
Register an HTTPS endpoint of yours; ChatKomodo posts every incoming message to it, signed with your secret:
curl -X POST "https://api.chatkomodo.com/v1/webhooks" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhooks/chatkomodo",
"secret": "a-long-random-secret-of-32-characters-or-more",
"events": [
"message.received",
"message.failed",
"session.disconnected"
]
}'const res = await fetch('https://api.chatkomodo.com/v1/webhooks', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"url": "https://example.com/webhooks/chatkomodo",
"secret": "a-long-random-secret-of-32-characters-or-more",
"events": [
"message.received",
"message.failed",
"session.disconnected"
]
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.code}: ${data.error}`);
console.log(data);import os
import requests
res = requests.post(
"https://api.chatkomodo.com/v1/webhooks",
headers={
"Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
},
json={
"url": "https://example.com/webhooks/chatkomodo",
"secret": "a-long-random-secret-of-32-characters-or-more",
"events": [
"message.received",
"message.failed",
"session.disconnected",
],
},
timeout=30,
)
res.raise_for_status()
print(res.json())<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$res = $client->request('POST', 'https://api.chatkomodo.com/v1/webhooks', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
'json' => [
'url' => 'https://example.com/webhooks/chatkomodo',
'secret' => 'a-long-random-secret-of-32-characters-or-more',
'events' => [
'message.received',
'message.failed',
'session.disconnected',
],
],
]);
print_r(json_decode((string) $res->getBody(), true));Then verify the signature of each delivery. That is it — next, read Sending messages for media, polls, idempotency and pacing.