. Create an API key under API keys.API reference · Account
Agency (resellers)
For resellers: create and manage client accounts, give them plans at your wholesale price from prepaid credit, top up, and show your own brand and domain to your clients. Ask us to make your account an agency first.
Get your agency
/v1/agencyYour reseller account: discount, prepaid credit, brand, custom domain, wholesale price of each plan and totals over your clients. Account owner or API key; not for support agents.
Responses
- 200The agency
Response fields
tenant_idstringrequiredstatusstringrequireddiscount_pctintegerrequiredcreditintegerrequiredPrepaid balance, rupiahcurrencystringrequiredbrandobjectrequiredbrand.namestring | nullrequiredShown to your clients instead of ChatKomodo;null= not white-labelledbrand.colorstring | nullrequired#rrggbbbrand.logo_urlstring | nullrequiredbrand.logo_keystring | nullrequiredbrand.support_phonestring | nullrequiredbrand.support_emailstring | nullrequiredbrand.agency_idstringrequireddomainstring | nullrequireddomain_statusstringrequireddomain_targetstringrequiredPoint a CNAME of your domain hereplansarray of objectrequiredplans[].idintegerrequiredplans[].namestringrequiredplans[].list_priceintegerrequiredMonthly list price, rupiahplans[].priceintegerrequiredYour monthly price after the discount, rupiahplans[].max_sessionsintegerrequiredplans[].max_messages_per_monthintegerrequiredmax_monthsintegerrequiredtotalsobjectrequiredtotals.clientsintegerrequiredtotals.activeintegerrequiredNot suspended, on a paid plantotals.devicesintegerrequiredtotals.messages_monthintegerrequiredtopupobjectrequiredtopup.minintegerrequiredtopup.maxintegerrequired
- 404
NOT_AN_AGENCY: this business is not a reseller
curl "https://api.chatkomodo.com/v1/agency" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY"const res = await fetch('https://api.chatkomodo.com/v1/agency', {
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/agency",
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/agency', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"tenant_id": "01JA5V6Q8M2H7G4K9P3T0R1S2X",
"status": "active",
"discount_pct": 12,
"credit": 1,
"currency": "IDR",
"brand": {
"name": "Example",
"color": "#0a7350",
"logo_url": "https://example.com/file.jpg",
"logo_key": "uploads/abc123.jpg",
"support_phone": "+447700900123",
"support_email": "[email protected]",
"agency_id": "01JA5V6Q8M2H7G4K9P3T0R1S2X"
},
"domain": "string",
"domain_status": "none",
"domain_target": "+447700900123",
"plans": [
{
"id": 1,
"name": "Example",
"list_price": 150000,
"price": 150000,
"max_sessions": 1,
"max_messages_per_month": 1
}
],
"max_months": 1,
"totals": {
"clients": 1,
"active": 1,
"devices": 1,
"messages_month": 1
},
"topup": {
"min": 1,
"max": 1
}
}Set your brand
/v1/agency/brandWhat your clients see instead of ChatKomodo: name (in the dashboard, sign-in codes and alerts), colour, logo (upload it first with POST /v1/media; PNG, JPEG, WebP or GIF) and a support contact. Send only the fields to change; null clears one. Recorded as agency.brand.
Request body
brand_namestring | nullbrand_colorstring | nulllogo_keystring | nullsupport_phonestring | nullsupport_emailstring | null
Responses
- 200The agency
Response fields
tenant_idstringrequiredstatusstringrequireddiscount_pctintegerrequiredcreditintegerrequiredPrepaid balance, rupiahcurrencystringrequiredbrandobjectrequiredbrand.namestring | nullrequiredShown to your clients instead of ChatKomodo;null= not white-labelledbrand.colorstring | nullrequired#rrggbbbrand.logo_urlstring | nullrequiredbrand.logo_keystring | nullrequiredbrand.support_phonestring | nullrequiredbrand.support_emailstring | nullrequiredbrand.agency_idstringrequireddomainstring | nullrequireddomain_statusstringrequireddomain_targetstringrequiredPoint a CNAME of your domain hereplansarray of objectrequiredplans[].idintegerrequiredplans[].namestringrequiredplans[].list_priceintegerrequiredMonthly list price, rupiahplans[].priceintegerrequiredYour monthly price after the discount, rupiahplans[].max_sessionsintegerrequiredplans[].max_messages_per_monthintegerrequiredmax_monthsintegerrequiredtotalsobjectrequiredtotals.clientsintegerrequiredtotals.activeintegerrequiredNot suspended, on a paid plantotals.devicesintegerrequiredtotals.messages_monthintegerrequiredtopupobjectrequiredtopup.minintegerrequiredtopup.maxintegerrequired
- 400
VALIDATION_FAILED - 404
NOT_AN_AGENCY: this business is not a reseller
curl -X PUT "https://api.chatkomodo.com/v1/agency/brand" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"brand_name": "string",
"brand_color": "#0a7350",
"logo_key": "uploads/abc123.jpg",
"support_phone": "+447700900123"
}'const res = await fetch('https://api.chatkomodo.com/v1/agency/brand', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"brand_name": "string",
"brand_color": "#0a7350",
"logo_key": "uploads/abc123.jpg",
"support_phone": "+447700900123"
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.code}: ${data.error}`);
console.log(data);import os
import requests
res = requests.put(
"https://api.chatkomodo.com/v1/agency/brand",
headers={
"Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
},
json={
"brand_name": "string",
"brand_color": "#0a7350",
"logo_key": "uploads/abc123.jpg",
"support_phone": "+447700900123",
},
timeout=30,
)
res.raise_for_status()
print(res.json())<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$res = $client->request('PUT', 'https://api.chatkomodo.com/v1/agency/brand', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
'json' => [
'brand_name' => 'string',
'brand_color' => '#0a7350',
'logo_key' => 'uploads/abc123.jpg',
'support_phone' => '+447700900123',
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"tenant_id": "01JA5V6Q8M2H7G4K9P3T0R1S2X",
"status": "active",
"discount_pct": 12,
"credit": 1,
"currency": "IDR",
"brand": {
"name": "Example",
"color": "#0a7350",
"logo_url": "https://example.com/file.jpg",
"logo_key": "uploads/abc123.jpg",
"support_phone": "+447700900123",
"support_email": "[email protected]",
"agency_id": "01JA5V6Q8M2H7G4K9P3T0R1S2X"
},
"domain": "string",
"domain_status": "none",
"domain_target": "+447700900123",
"plans": [
{
"id": 1,
"name": "Example",
"list_price": 150000,
"price": 150000,
"max_sessions": 1,
"max_messages_per_month": 1
}
],
"max_months": 1,
"totals": {
"clients": 1,
"active": 1,
"devices": 1,
"messages_month": 1
},
"topup": {
"min": 1,
"max": 1
}
}Set your custom domain
/v1/agency/domainDashboard loginYour own address for clients to sign in (e.g. app.youragency.com). Point a CNAME at domain_target; the domain becomes active once we have connected it (usually within a working day). null removes it. Account owner only. Recorded as agency.domain.
Request body
domainstring | nullrequired
Responses
- 200The agency
Response fields
tenant_idstringrequiredstatusstringrequireddiscount_pctintegerrequiredcreditintegerrequiredPrepaid balance, rupiahcurrencystringrequiredbrandobjectrequiredbrand.namestring | nullrequiredShown to your clients instead of ChatKomodo;null= not white-labelledbrand.colorstring | nullrequired#rrggbbbrand.logo_urlstring | nullrequiredbrand.logo_keystring | nullrequiredbrand.support_phonestring | nullrequiredbrand.support_emailstring | nullrequiredbrand.agency_idstringrequireddomainstring | nullrequireddomain_statusstringrequireddomain_targetstringrequiredPoint a CNAME of your domain hereplansarray of objectrequiredplans[].idintegerrequiredplans[].namestringrequiredplans[].list_priceintegerrequiredMonthly list price, rupiahplans[].priceintegerrequiredYour monthly price after the discount, rupiahplans[].max_sessionsintegerrequiredplans[].max_messages_per_monthintegerrequiredmax_monthsintegerrequiredtotalsobjectrequiredtotals.clientsintegerrequiredtotals.activeintegerrequiredNot suspended, on a paid plantotals.devicesintegerrequiredtotals.messages_monthintegerrequiredtopupobjectrequiredtopup.minintegerrequiredtopup.maxintegerrequired
- 400
VALIDATION_FAILED - 404
NOT_AN_AGENCY: this business is not a reseller - 409
DOMAIN_TAKEN
curl -X PUT "https://api.chatkomodo.com/v1/agency/domain" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"domain": "string"
}'const res = await fetch('https://api.chatkomodo.com/v1/agency/domain', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"domain": "string"
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.code}: ${data.error}`);
console.log(data);import os
import requests
res = requests.put(
"https://api.chatkomodo.com/v1/agency/domain",
headers={
"Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
},
json={
"domain": "string",
},
timeout=30,
)
res.raise_for_status()
print(res.json())<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client();
$res = $client->request('PUT', 'https://api.chatkomodo.com/v1/agency/domain', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
'json' => [
'domain' => 'string',
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"tenant_id": "01JA5V6Q8M2H7G4K9P3T0R1S2X",
"status": "active",
"discount_pct": 12,
"credit": 1,
"currency": "IDR",
"brand": {
"name": "Example",
"color": "#0a7350",
"logo_url": "https://example.com/file.jpg",
"logo_key": "uploads/abc123.jpg",
"support_phone": "+447700900123",
"support_email": "[email protected]",
"agency_id": "01JA5V6Q8M2H7G4K9P3T0R1S2X"
},
"domain": "string",
"domain_status": "none",
"domain_target": "+447700900123",
"plans": [
{
"id": 1,
"name": "Example",
"list_price": 150000,
"price": 150000,
"max_sessions": 1,
"max_messages_per_month": 1
}
],
"max_months": 1,
"totals": {
"clients": 1,
"active": 1,
"devices": 1,
"messages_month": 1
},
"topup": {
"min": 1,
"max": 1
}
}List your clients
/v1/agency/clientsYour client businesses with their plan, devices and messages this month.
Responses
- 200Clients
Response fields
clientsarray of objectrequiredclients[].idstringrequiredclients[].namestringrequiredclients[].phonestring | nullrequiredThe owner's WhatsApp number (signs in with a code)clients[].plan_idinteger | nullrequiredclients[].plan_namestring | nullrequiredclients[].plan_active_untilinteger | nullrequiredUnix time in millisecondsclients[].suspendedbooleanrequiredclients[].created_atintegerrequiredUnix time in millisecondsclients[].devicesintegerrequiredclients[].connectedintegerrequiredclients[].messages_monthintegerrequired
- 404
NOT_AN_AGENCY: this business is not a reseller
curl "https://api.chatkomodo.com/v1/agency/clients" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY"const res = await fetch('https://api.chatkomodo.com/v1/agency/clients', {
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/agency/clients",
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/agency/clients', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"clients": [
{
"id": "01JA5V6Q8M2H7G4K9P3T0R1S2X",
"name": "Example",
"phone": "+447700900123",
"plan_id": 1,
"plan_name": "string",
"plan_active_until": 1767225600000,
"suspended": true,
"created_at": 1767225600000,
"devices": 1,
"connected": 1,
"messages_month": 1
}
]
}Create a client
/v1/agency/clientsA new business managed by you. Its owner signs in with a WhatsApp code on phone (or the one-time access_code). With plan_id, the plan is paid from your credit at your wholesale price for months (1-12); without, the client starts on Free. The API key and access code are shown only once. Recorded as agency.client_create.
Request body
namestringrequiredphonestringrequiredInternational formatplan_idinteger | nullmonthsinteger
Responses
- 201Created
Response fields
client_idstringrequiredphonestringrequiredapi_keystringrequiredaccess_codestringrequiredplanobject | nullrequiredplan.plan_idintegerrequiredplan.monthsintegerrequiredplan.costintegerrequiredplan.active_untilintegerrequiredUnix time in millisecondsplan.creditintegerrequired
- 400
VALIDATION_FAILEDorINVALID_NUMBER - 402
INSUFFICIENT_CREDIT(withcostandcredit) - 404
NOT_AN_AGENCY: this business is not a reseller - 409
PHONE_IN_USE
curl -X POST "https://api.chatkomodo.com/v1/agency/clients" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Example",
"phone": "+447700900123",
"plan_id": 1,
"months": 1
}'const res = await fetch('https://api.chatkomodo.com/v1/agency/clients', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Example",
"phone": "+447700900123",
"plan_id": 1,
"months": 1
}),
});
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/agency/clients",
headers={
"Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
},
json={
"name": "Example",
"phone": "+447700900123",
"plan_id": 1,
"months": 1,
},
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/agency/clients', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
'json' => [
'name' => 'Example',
'phone' => '+447700900123',
'plan_id' => 1,
'months' => 1,
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"client_id": "01JA5V6Q8M2H7G4K9P3T0R1S2X",
"phone": "+447700900123",
"api_key": "uploads/abc123.jpg",
"access_code": "482913",
"plan": {
"plan_id": 1,
"months": 1,
"cost": 1,
"active_until": 1767225600000,
"credit": 1
}
}Give a client a plan
/v1/agency/clients/{id}/planPaid from your credit at your wholesale price. The same plan adds to the current period; another plan starts now (the rest of the old period is not refunded). Recorded as agency.client_plan.
Path parameters
idstringrequired
Request body
plan_idintegerrequiredmonthsinteger
Responses
- 200Done
Response fields
okbooleanrequiredcostintegerrequiredcreditintegerrequiredactive_untilintegerrequiredUnix time in milliseconds
- 400
VALIDATION_FAILED - 402
INSUFFICIENT_CREDIT - 404
NOT_FOUND/NOT_AN_AGENCY
curl -X POST "https://api.chatkomodo.com/v1/agency/clients/ID/plan" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"plan_id": 1,
"months": 1
}'const res = await fetch('https://api.chatkomodo.com/v1/agency/clients/ID/plan', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"plan_id": 1,
"months": 1
}),
});
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/agency/clients/ID/plan",
headers={
"Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
},
json={
"plan_id": 1,
"months": 1,
},
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/agency/clients/ID/plan', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
'json' => [
'plan_id' => 1,
'months' => 1,
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"ok": true,
"cost": 1,
"credit": 1,
"active_until": 1767225600000
}Suspend a client
/v1/agency/clients/{id}/suspendSigns the client out and disconnects its devices until reactivated. Recorded as agency.client_suspend.
Path parameters
idstringrequired
Responses
- 200Done
Response fields
okbooleanrequiredsuspendedbooleanrequired
- 404
NOT_FOUND
curl -X POST "https://api.chatkomodo.com/v1/agency/clients/ID/suspend" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY"const res = await fetch('https://api.chatkomodo.com/v1/agency/clients/ID/suspend', {
method: 'POST',
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.post(
"https://api.chatkomodo.com/v1/agency/clients/ID/suspend",
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('POST', 'https://api.chatkomodo.com/v1/agency/clients/ID/suspend', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"ok": true,
"suspended": true
}Reactivate a client
/v1/agency/clients/{id}/activateLets the client sign in again and reconnects its devices. Recorded as agency.client_activate.
Path parameters
idstringrequired
Responses
- 200Done
Response fields
okbooleanrequiredsuspendedbooleanrequired
- 404
NOT_FOUND
curl -X POST "https://api.chatkomodo.com/v1/agency/clients/ID/activate" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY"const res = await fetch('https://api.chatkomodo.com/v1/agency/clients/ID/activate', {
method: 'POST',
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.post(
"https://api.chatkomodo.com/v1/agency/clients/ID/activate",
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('POST', 'https://api.chatkomodo.com/v1/agency/clients/ID/activate', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"ok": true,
"suspended": true
}Delete a client
/v1/agency/clients/{id}Dashboard loginDeletes the client business and everything it holds, for good. confirm must repeat its name. Account owner only. Recorded as agency.client_delete.
Path parameters
idstringrequired
Request body
confirmstringrequired
Responses
- 200Deleted
Response fields
okbooleanrequiredsessionsintegerrequired
- 400
CONFIRMATION_REQUIRED - 404
NOT_FOUND
curl -X DELETE "https://api.chatkomodo.com/v1/agency/clients/ID" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"confirm": "string"
}'const res = await fetch('https://api.chatkomodo.com/v1/agency/clients/ID', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"confirm": "string"
}),
});
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/agency/clients/ID",
headers={
"Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
},
json={
"confirm": "string",
},
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/agency/clients/ID', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
'json' => [
'confirm' => 'string',
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"ok": true,
"sessions": 1
}Open a client's dashboard
/v1/agency/clients/{id}/sign-inDashboard loginTokens to act as the client's owner (to set up devices, automations…). The session is listed in the client's signed-in devices as "Agency" and recorded in both audit logs (agency.client_sign_in, auth.agency_sign_in). Agency owner only (not an API key).
Path parameters
idstringrequired
Responses
- 200Tokens
Response fields
tokenstringrequiredrefresh_tokenstringrequiredrolestringrequired
- 403
FORBIDDEN - 409The client is suspended
curl -X POST "https://api.chatkomodo.com/v1/agency/clients/ID/sign-in" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY"const res = await fetch('https://api.chatkomodo.com/v1/agency/clients/ID/sign-in', {
method: 'POST',
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.post(
"https://api.chatkomodo.com/v1/agency/clients/ID/sign-in",
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('POST', 'https://api.chatkomodo.com/v1/agency/clients/ID/sign-in', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"token": "eyJhbGciOiJIUzI1NiIs…",
"refresh_token": "eyJhbGciOiJIUzI1NiIs…",
"role": "admin"
}Credit history
/v1/agency/ledgerEvery top-up, plan purchase and adjustment, newest first, with the balance after each. Page with before = next_before.
Query parameters
beforestringlimitstring
Responses
- 200Entries
Response fields
entriesarray of objectrequiredentries[].idintegerrequiredentries[].atintegerrequiredUnix time in millisecondsentries[].kindstringrequiredentries[].amountintegerrequiredRupiah; negative = spententries[].balanceintegerrequiredBalance after this entryentries[].client_idstring | nullrequiredentries[].client_namestring | nullrequiredentries[].plan_idinteger | nullrequiredentries[].plan_namestring | nullrequiredentries[].monthsinteger | nullrequiredentries[].order_idstring | nullrequiredentries[].notestring | nullrequirednext_beforeinteger | nullrequired
- 404
NOT_AN_AGENCY: this business is not a reseller
curl "https://api.chatkomodo.com/v1/agency/ledger" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY"const res = await fetch('https://api.chatkomodo.com/v1/agency/ledger', {
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/agency/ledger",
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/agency/ledger', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"entries": [
{
"id": 1,
"at": 1767225600000,
"kind": "topup",
"amount": 150000,
"balance": 1,
"client_id": "01JA5V6Q8M2H7G4K9P3T0R1S2X",
"client_name": "string",
"plan_id": 1,
"plan_name": "string",
"months": 1,
"order_id": "01JA5V6Q8M2H7G4K9P3T0R1S2X",
"note": "Prefers delivery after 5 pm"
}
],
"next_before": 1767225600000
}Top up your credit
/v1/agency/topupDashboard loginCreates a payment for amount rupiah (50 000 - 100 000 000) with a rupiah payment method; the credit is added when the payment is confirmed (webhook, or POST /v1/billing/invoices/{order_id}/confirm). Account owner only. Recorded as agency.topup.
Request body
amountintegerrequiredproviderstring
Responses
- 201Payment created
Response fields
order_idstringrequiredamountintegerrequiredcurrencystringrequiredproviderstringrequiredpay_urlstringrequired
- 400
VALIDATION_FAILED - 503
NOT_CONFIGURED
curl -X POST "https://api.chatkomodo.com/v1/agency/topup" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 150000,
"provider": "string"
}'const res = await fetch('https://api.chatkomodo.com/v1/agency/topup', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"amount": 150000,
"provider": "string"
}),
});
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/agency/topup",
headers={
"Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
},
json={
"amount": 150000,
"provider": "string",
},
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/agency/topup', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
'json' => [
'amount' => 150000,
'provider' => 'string',
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"order_id": "01JA5V6Q8M2H7G4K9P3T0R1S2X",
"amount": 150000,
"currency": "IDR",
"provider": "string",
"pay_url": "https://example.com/file.jpg"
}Brand of a sign-in domain
/public/brandNo authenticationPublic. The brand of an agency's activated custom domain (used by the sign-in page), or null.
Query parameters
hoststringrequired
Responses
- 200Brand
Response fields
brandobject | nullrequiredbrand.namestringrequiredbrand.colorstring | nullrequiredbrand.logo_urlstring | nullrequiredbrand.support_phonestring | nullrequiredbrand.support_emailstring | nullrequiredbrand.agency_idstringrequired
curl "https://api.chatkomodo.com/public/brand?host=string"const res = await fetch('https://api.chatkomodo.com/public/brand?host=string', {
method: 'GET',
});
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/public/brand?host=string",
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/public/brand?host=string', [
]);
print_r(json_decode((string) $res->getBody(), true));{
"brand": {
"name": "Example",
"color": "#0a7350",
"logo_url": "https://example.com/file.jpg",
"support_phone": "+447700900123",
"support_email": "[email protected]",
"agency_id": "01JA5V6Q8M2H7G4K9P3T0R1S2X"
}
}An agency's logo
/public/brand/{agency}/logoNo authenticationPublic. The logo image of an active agency.
Path parameters
agencystringrequired
Responses
- 200The image
- 404No logo
curl "https://api.chatkomodo.com/public/brand/AGENCY/logo"const res = await fetch('https://api.chatkomodo.com/public/brand/AGENCY/logo', {
method: 'GET',
});
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/public/brand/AGENCY/logo",
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/public/brand/AGENCY/logo', [
]);
print_r(json_decode((string) $res->getBody(), true));image/png — the file itself.