. Create an API key under API keys.API reference · Messaging
Rotators
Spread sending over a pool of devices, round-robin or at random.
List rotators
/v1/rotatorsRotators of the tenant, newest first.
Responses
- 200Rotators
Response fields
rotatorsarray of objectrequiredrotators[].idstringrequiredrotators[].api_key_idstringrequiredOwning tenantrotators[].namestringrequiredrotators[].session_idsarray of stringrequiredDevices in the poolrotators[].strategystringrequiredrandom(default) orround-robin; any other stored value behaves likerandomrotators[].last_used_idxinteger | nullrequiredRound-robin positionrotators[].created_atintegerrequiredUnix time in milliseconds
- 401Missing, invalid or expired credentials
curl "https://api.chatkomodo.com/v1/rotators" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY"const res = await fetch('https://api.chatkomodo.com/v1/rotators', {
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/rotators",
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/rotators', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"rotators": [
{
"id": "01JA5V6Q8M2H7G4K9P3T0R1S2X",
"api_key_id": "01JA5V6Q8M2H7G4K9P3T0R1S2X",
"name": "Sales numbers",
"session_ids": [
"YOUR_DEVICE_ID"
],
"strategy": "round-robin",
"last_used_idx": 12,
"created_at": 1767225600000
}
]
}Create a rotator
/v1/rotatorsCreates a pool of devices that outgoing messages are spread over (see POST /v1/rotators/{id}/send). The handler does not validate name, but it is required.
Request body
namestringrequiredLabelsession_idsarray of stringDevice ids in the pool (default: empty); every one must belong to the tenantstrategystringrandom(default) orround-robin. Not validated: any other value behaves likerandom
Responses
- 201Created
Response fields
idstringrequired
- 400
session_idsmust be an array of the tenant's own device ids (nocode) - 401Missing, invalid or expired credentials
- 403Forbidden for a customer-service agent login (
Agent access is not allowed for this operation) and an API key restricted to specific sessions (KEY_SCOPE_FORBIDDEN)
curl -X POST "https://api.chatkomodo.com/v1/rotators" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Sales numbers",
"session_ids": [
"YOUR_DEVICE_ID"
],
"strategy": "round-robin"
}'const res = await fetch('https://api.chatkomodo.com/v1/rotators', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Sales numbers",
"session_ids": [
"YOUR_DEVICE_ID"
],
"strategy": "round-robin"
}),
});
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/rotators",
headers={
"Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
},
json={
"name": "Sales numbers",
"session_ids": [
"YOUR_DEVICE_ID",
],
"strategy": "round-robin",
},
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/rotators', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
'json' => [
'name' => 'Sales numbers',
'session_ids' => [
'YOUR_DEVICE_ID',
],
'strategy' => 'round-robin',
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"id": "01JA5V6Q8M2H7G4K9P3T0R1S2X"
}Edit a rotator
/v1/rotators/{id}Changes the name, device list and/or strategy. Send only the fields to change; an empty name or strategy is ignored.
Path parameters
idstringrequiredRotator id
Request body
namestringsession_idsarray of stringDevice ids; every one must belong to the tenantstrategystringrandom(default) orround-robin. Not validated: any other value behaves likerandom
Responses
- 200Updated
Response fields
okbooleanrequired
- 400
session_idsmust be an array of the tenant's own device ids (nocode) - 401Missing, invalid or expired credentials
- 403Forbidden for a customer-service agent login (
Agent access is not allowed for this operation) and an API key restricted to specific sessions (KEY_SCOPE_FORBIDDEN) - 404Rotator not found (no
code)
curl -X PATCH "https://api.chatkomodo.com/v1/rotators/ID" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Sales numbers",
"session_ids": [
"YOUR_DEVICE_ID"
],
"strategy": "round-robin"
}'const res = await fetch('https://api.chatkomodo.com/v1/rotators/ID', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Sales numbers",
"session_ids": [
"YOUR_DEVICE_ID"
],
"strategy": "round-robin"
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.code}: ${data.error}`);
console.log(data);import os
import requests
res = requests.patch(
"https://api.chatkomodo.com/v1/rotators/ID",
headers={
"Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
},
json={
"name": "Sales numbers",
"session_ids": [
"YOUR_DEVICE_ID",
],
"strategy": "round-robin",
},
timeout=30,
)
res.raise_for_status()
print(res.json())<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$res = $client->request('PATCH', 'https://api.chatkomodo.com/v1/rotators/ID', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
'json' => [
'name' => 'Sales numbers',
'session_ids' => [
'YOUR_DEVICE_ID',
],
'strategy' => 'round-robin',
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"ok": true
}Delete a rotator
/v1/rotators/{id}Permanently deletes a rotator. The devices in it are not affected.
Path parameters
idstringrequiredRotator id
Responses
- 200Deleted
Response fields
okbooleanrequired
- 401Missing, invalid or expired credentials
- 403Forbidden for a customer-service agent login (
Agent access is not allowed for this operation) and an API key restricted to specific sessions (KEY_SCOPE_FORBIDDEN) - 404Rotator not found (no
code)
curl -X DELETE "https://api.chatkomodo.com/v1/rotators/ID" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY"const res = await fetch('https://api.chatkomodo.com/v1/rotators/ID', {
method: 'DELETE',
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.delete(
"https://api.chatkomodo.com/v1/rotators/ID",
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('DELETE', 'https://api.chatkomodo.com/v1/rotators/ID', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"ok": true
}Send through a rotator
/v1/rotators/{id}/sendSends one message through one of the rotator's connected devices, picked by its strategy (round-robin or random). It is a 1:1 send like POST /v1/sessions/{id}/messages: an opted-out recipient still receives it with a RECIPIENT_OPTED_OUT warning, or is refused with 409 when the tenant enabled strict consent (enforce_api). The body fields are passed to the device as given and are not validated here beyond chat_id.
Path parameters
idstringrequiredRotator id
Request body
chat_idstringrequiredRecipient JID, or a phone number (international format; local numbers use the business country orcountry_code)country_codestringCalling code used only for a local-format numbertypestringMessage type as inPOST /v1/sessions/{sessionId}/messages(textby default)bodystringText contentmedia_r2_keystringKey of an uploaded media filecaptionstringlocationobjectlocation.latnumberrequiredlocation.lngnumberrequiredpoll_namestringchoicesarray of stringreply_tostringId of the message to quote
Responses
- 202Accepted for sending
Response fields
message_idstringrequiredId of the logged messagesession_usedstringrequiredDevice the message was sent fromstatusstringrequiredSend status reported by the device, e.g.queuedorsentqueued_positionintegerwarningsarray of objectRECIPIENT_OPTED_OUTwhen the recipient has opted outwarnings[].codestringrequiredwarnings[].messagestringrequired
- 400
chat_idmissing (nocode),INVALID_NUMBERorINVALID_JID - 401Missing, invalid or expired credentials
- 403Forbidden for a customer-service agent login (
Agent access is not allowed for this operation) and an API key restricted to specific sessions (KEY_SCOPE_FORBIDDEN) - 404Rotator not found (no
code) - 409None of the rotator's devices is connected (no
code), or the recipient opted out and strict consent is on (RECIPIENT_OPTED_OUT)
curl -X POST "https://api.chatkomodo.com/v1/rotators/ID/send" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"chat_id": "+447700900123",
"type": "text",
"body": "Thanks for your order! We will confirm shortly."
}'const res = await fetch('https://api.chatkomodo.com/v1/rotators/ID/send', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"chat_id": "+447700900123",
"type": "text",
"body": "Thanks for your order! We will confirm shortly."
}),
});
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/rotators/ID/send",
headers={
"Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
},
json={
"chat_id": "+447700900123",
"type": "text",
"body": "Thanks for your order! We will confirm shortly.",
},
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/rotators/ID/send', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
'json' => [
'chat_id' => '+447700900123',
'type' => 'text',
'body' => 'Thanks for your order! We will confirm shortly.',
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"message_id": "01JA5V6Q8M2H7G4K9P3T0R1S2X",
"session_used": "string",
"status": "active",
"queued_position": 1,
"warnings": [
{
"code": "RECIPIENT_OPTED_OUT",
"message": "Hi Sam, your order has shipped."
}
]
}