ChatKomodo Docs Home Sign in

API reference · Messaging

Rotators

Spread sending over a pool of devices, round-robin or at random.

List rotators

GET/v1/rotators

Rotators of the tenant, newest first.

Responses

  • 200Rotators
    Response fields
    • rotatorsarray of objectrequired
    • rotators[].idstringrequired
    • rotators[].api_key_idstringrequired
      Owning tenant
    • rotators[].namestringrequired
    • rotators[].session_idsarray of stringrequired
      Devices in the pool
    • rotators[].strategystringrequired
      random (default) or round-robin; any other stored value behaves like random
    • rotators[].last_used_idxinteger | nullrequired
      Round-robin position
    • rotators[].created_atintegerrequired
      Unix time in milliseconds
  • 401Missing, invalid or expired credentials
Request
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));
Response 200
{
  "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

POST/v1/rotators

Creates 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

  • namestringrequired
    Label
  • session_idsarray of string
    Device ids in the pool (default: empty); every one must belong to the tenant
  • strategystring
    random (default) or round-robin. Not validated: any other value behaves like random

Responses

  • 201Created
    Response fields
    • idstringrequired
  • 400session_ids must be an array of the tenant's own device ids (no code)
  • 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)
Request
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));
Response 201
{
  "id": "01JA5V6Q8M2H7G4K9P3T0R1S2X"
}

Edit a rotator

PATCH/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

  • idstringrequired
    Rotator id

Request body

  • namestring
  • session_idsarray of string
    Device ids; every one must belong to the tenant
  • strategystring
    random (default) or round-robin. Not validated: any other value behaves like random

Responses

  • 200Updated
    Response fields
    • okbooleanrequired
  • 400session_ids must be an array of the tenant's own device ids (no code)
  • 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)
Request
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));
Response 200
{
  "ok": true
}

Delete a rotator

DEL/v1/rotators/{id}

Permanently deletes a rotator. The devices in it are not affected.

Path parameters

  • idstringrequired
    Rotator 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)
Request
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));
Response 200
{
  "ok": true
}

Send through a rotator

POST/v1/rotators/{id}/send

Sends 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

  • idstringrequired
    Rotator id

Request body

  • chat_idstringrequired
    Recipient JID, or a phone number (international format; local numbers use the business country or country_code)
  • country_codestring
    Calling code used only for a local-format number
  • typestring
    Message type as in POST /v1/sessions/{sessionId}/messages (text by default)
  • bodystring
    Text content
  • media_r2_keystring
    Key of an uploaded media file
  • captionstring
  • locationobject
  • location.latnumberrequired
  • location.lngnumberrequired
  • poll_namestring
  • choicesarray of string
  • reply_tostring
    Id of the message to quote

Responses

  • 202Accepted for sending
    Response fields
    • message_idstringrequired
      Id of the logged message
    • session_usedstringrequired
      Device the message was sent from
    • statusstringrequired
      Send status reported by the device, e.g. queued or sent
    • queued_positioninteger
    • warningsarray of object
      RECIPIENT_OPTED_OUT when the recipient has opted out
    • warnings[].codestringrequired
    • warnings[].messagestringrequired
  • 400chat_id missing (no code), INVALID_NUMBER or INVALID_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)
Request
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));
Response 202
{
  "message_id": "01JA5V6Q8M2H7G4K9P3T0R1S2X",
  "session_used": "string",
  "status": "active",
  "queued_position": 1,
  "warnings": [
    {
      "code": "RECIPIENT_OPTED_OUT",
      "message": "Hi Sam, your order has shipped."
    }
  ]
}