. Create an API key under API keys.API reference · Integrations
API keys
Child keys for separate integrations, each with its own request limit and optional device scope. Managed from a dashboard login.
List API keys
/v1/api-keysDashboard loginLists the tenant's primary key and its child keys (primary first, then newest first, max 1 000), revoked ones included. Only the 8-character prefix is returned, never the key itself. Readable with an API key as well as from a dashboard login.
Responses
- 200Keys
Response fields
api_keysarray of objectrequiredapi_keys[].idstringrequiredapi_keys[].namestringrequiredapi_keys[].prefixstringrequiredFirst 8 characters of the key, safe to display. The full key is only returned once, when it is createdapi_keys[].is_primarybooleanrequiredapi_keys[].rate_limit_per_minuteintegerrequiredapi_keys[].created_atintegerrequiredUnix time in millisecondsapi_keys[].last_used_atinteger | nullrequiredUnix time in milliseconds of the last authenticated request (updated at most once a minute), or null if never usedapi_keys[].revoked_atinteger | nullrequiredWhen the key was revoked, or null while it is active
- 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 "https://api.chatkomodo.com/v1/api-keys" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY"const res = await fetch('https://api.chatkomodo.com/v1/api-keys', {
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/api-keys",
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/api-keys', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"api_keys": [
{
"id": "01JA5V6Q8M2H7G4K9P3T0R1S2X",
"name": "Shop integration",
"prefix": "string",
"is_primary": true,
"rate_limit_per_minute": 50,
"created_at": 1767225600000,
"last_used_at": 1767225600000,
"revoked_at": 1767225600000
}
]
}Create a child API key
/v1/api-keysDashboard loginCreates a child key that acts as the tenant (same devices, quota, plan and settings) but has its own per-minute request limit and can be revoked on its own. The full key is returned once, in this response only. Needs a dashboard login: an API key cannot mint keys. With the platform admin secret the new key is a separate standalone tenant on the Free plan instead.
Request body
namestringLabel, 1-64 characters (defaultunnamed)rate_limit_per_minuteintegerRequests per minute this key may make, across all/v1endpoints (1-10 000, default 300). Capped to the plan ceiling: 5 times the plan's send rate per minute, at least 300 (600 on Pro with the default send rates)
Responses
- 201Key created
Response fields
idstringrequiredkeystringrequiredThe secret API key. Shown only in this response; store it securelyprefixstringrequiredFirst 8 characters of the keynamestringrequired
- 400Body is not valid JSON (
INVALID_JSON) or fails validation (VALIDATION_FAILED) - 401Missing, invalid or expired credentials
- 403Forbidden.
KEY_MANAGEMENT_REQUIRES_LOGINwhen the request was authenticated with an API key (keys can only be managed from a dashboard login). Also refused, without a code, for a customer-service agent login, and withKEY_SCOPE_FORBIDDENfor a session-restricted key
curl -X POST "https://api.chatkomodo.com/v1/api-keys" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Shop integration",
"rate_limit_per_minute": 50
}'const res = await fetch('https://api.chatkomodo.com/v1/api-keys', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Shop integration",
"rate_limit_per_minute": 50
}),
});
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/api-keys",
headers={
"Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
},
json={
"name": "Shop integration",
"rate_limit_per_minute": 50,
},
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/api-keys', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
'json' => [
'name' => 'Shop integration',
'rate_limit_per_minute' => 50,
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"id": "01JA5V6Q8M2H7G4K9P3T0R1S2X",
"key": "uploads/abc123.jpg",
"prefix": "string",
"name": "Shop integration"
}Rename a key or change its rate limit
/v1/api-keys/{id}Dashboard loginUpdates the name and/or the per-minute rate limit of the tenant's primary key or one of its child keys. The rate limit is the number of requests per minute the key may make with its API key; it is capped to the plan ceiling (5 times the plan's send rate per minute, at least 300), the response returns the value that was applied, and a change takes effect on the next request. Needs a dashboard login.
Path parameters
idstringrequiredAPI key id
Request body
namestringLabel, 1-64 charactersrate_limit_per_minuteintegerRequests per minute this key may make, across all/v1endpoints (1-10 000, default 300). Capped to the plan ceiling: 5 times the plan's send rate per minute, at least 300 (600 on Pro with the default send rates)
Responses
- 200Updated
Response fields
okbooleanrequiredrate_limit_per_minuteintegerrequiredRate limit now in force (after the plan cap)
- 400Body is not valid JSON (
INVALID_JSON) or fails validation (VALIDATION_FAILED) - 401Missing, invalid or expired credentials
- 403Forbidden.
KEY_MANAGEMENT_REQUIRES_LOGINwhen the request was authenticated with an API key (keys can only be managed from a dashboard login). Also refused, without a code, for a customer-service agent login, and withKEY_SCOPE_FORBIDDENfor a session-restricted key - 404API key not found, or it belongs to another tenant (
NOT_FOUND)
curl -X PATCH "https://api.chatkomodo.com/v1/api-keys/ID" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Shop integration",
"rate_limit_per_minute": 50
}'const res = await fetch('https://api.chatkomodo.com/v1/api-keys/ID', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.CHATKOMODO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Shop integration",
"rate_limit_per_minute": 50
}),
});
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/api-keys/ID",
headers={
"Authorization": f"Bearer {os.environ['CHATKOMODO_API_KEY']}",
},
json={
"name": "Shop integration",
"rate_limit_per_minute": 50,
},
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/api-keys/ID', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
'json' => [
'name' => 'Shop integration',
'rate_limit_per_minute' => 50,
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"ok": true,
"rate_limit_per_minute": 50
}Revoke a child API key (alias)
/v1/api-keys/{id}Dashboard loginAlias of POST /v1/api-keys/{id}/revoke: the key is revoked, not removed, and stays in the list with revoked_at set. The primary key cannot be revoked. Needs a dashboard login.
Path parameters
idstringrequiredAPI key id
Responses
- 200Revoked (also returned when the key was already revoked)
Response fields
okbooleanrequired
- 400The tenant's own primary key cannot be revoked, because it would lock the tenant out of its dashboard (
CANNOT_REVOKE_PRIMARY) - 401Missing, invalid or expired credentials
- 403Forbidden.
KEY_MANAGEMENT_REQUIRES_LOGINwhen the request was authenticated with an API key (keys can only be managed from a dashboard login). Also refused, without a code, for a customer-service agent login, and withKEY_SCOPE_FORBIDDENfor a session-restricted key - 404API key not found, or it belongs to another tenant (
NOT_FOUND)
curl -X DELETE "https://api.chatkomodo.com/v1/api-keys/ID" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY"const res = await fetch('https://api.chatkomodo.com/v1/api-keys/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/api-keys/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/api-keys/ID', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"ok": true
}Revoke a child API key
/v1/api-keys/{id}/revokeDashboard loginRevokes one of the tenant's child keys: it stops authenticating immediately. The key stays in the list with revoked_at set. The primary key cannot be revoked. Same effect as DELETE /v1/api-keys/{id}. Needs a dashboard login.
Path parameters
idstringrequiredAPI key id
Responses
- 200Revoked (also returned when the key was already revoked)
Response fields
okbooleanrequired
- 400The tenant's own primary key cannot be revoked, because it would lock the tenant out of its dashboard (
CANNOT_REVOKE_PRIMARY) - 401Missing, invalid or expired credentials
- 403Forbidden.
KEY_MANAGEMENT_REQUIRES_LOGINwhen the request was authenticated with an API key (keys can only be managed from a dashboard login). Also refused, without a code, for a customer-service agent login, and withKEY_SCOPE_FORBIDDENfor a session-restricted key - 404API key not found, or it belongs to another tenant (
NOT_FOUND)
curl -X POST "https://api.chatkomodo.com/v1/api-keys/ID/revoke" \
-H "Authorization: Bearer $CHATKOMODO_API_KEY"const res = await fetch('https://api.chatkomodo.com/v1/api-keys/ID/revoke', {
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/api-keys/ID/revoke",
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/api-keys/ID/revoke', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHATKOMODO_API_KEY'),
],
]);
print_r(json_decode((string) $res->getBody(), true));{
"ok": true
}