API reference
The API channel (send a customer message, read the reply) with an OpenAPI file, and the endpoints the website chat window uses.
Kumoda has one API you build on: the API channel. Your own system sends a customer's message to one of your agents and reads the reply. It is the same conversation as on WhatsApp or the website chat window, with the same credits and the same handover to a person.
The OpenAPI file is at /openapi.json. Import it into Postman, Insomnia or any OpenAPI tool.
The API channel is for servers. It gives no browser (CORS) access, so call it from your backend, not from a web page. To put a chat on a web page, use the website chat window.
Set it up
Create the connection in the app: Channels, Add channel, API, choose the agent, Create the API connection (see Channels). You get two things:
- the address, which has the form
https://agents.kumoda.io/api/v1/agents/<key>/messages, where<key>is the letteraand 24 lowercase hex characters, and - the secret, which starts with
ksk_. It is shown only once and only a hash is kept. New secret replaces it, and the old one stops working at once.
Every call carries the secret as a bearer token: Authorization: Bearer ksk_…. A wrong key and a wrong secret get the same answer, so neither can be guessed from it.
An agent has one API connection, and an account can have up to 10. A paused connection refuses new messages (503).
Send a message
POST /api/v1/agents/<key>/messages with a JSON body.
| Field | Required | What it is |
|---|---|---|
contact | yes | Your own id for the customer: 3 to 60 letters, numbers, dots, dashes, colons or underscores. Each contact is one conversation. |
text | yes | The customer's message. Over 4,000 characters is refused (413). Only the first 1,500 characters are given to the agent. |
name | no | The customer's name, up to 80 characters. |
email | no | The customer's email. Ignored if it is not a valid address. |
phone | no | The customer's phone number, up to 30 characters. Only digits, +, spaces, brackets and dashes are kept. |
messageId | no | Your id for this message (up to 64 letters, numbers, dots, dashes, colons or underscores). Sending the same one again is not answered twice, so a retry is safe. |
wait | no | Seconds to wait for the reply, up to 25. The default is 20. Use 0 to return straight away and read the reply later. |
Give an email or phone and the customer becomes a contact in Kumoda.
curl -X POST https://agents.kumoda.io/api/v1/agents/YOUR_KEY/messages \
-H "Authorization: Bearer YOUR_SECRET" -H "Content-Type: application/json" \
-d '{"contact":"customer-123","text":"Hi, are you open today?","name":"Ada","email":"ada@example.com"}'The message is saved before the call answers. The answer is a JSON object with a status:
status | Meaning |
|---|---|
replied | The reply is in reply. from says who wrote it (agent or human), and id is its message id. |
pending | No reply yet (the wait ran out). Read it with GET. |
duplicate | This messageId was already sent. Nothing new was saved. |
with_a_person | A person has taken the conversation over, so the agent will not answer. |
{ "status": "replied", "reply": "Yes, we are open until 6pm today.", "from": "agent", "id": 1042 }Read a conversation
GET /api/v1/agents/<key>/messages?contact=customer-123&after=0
Returns the contact's messages after a message id, oldest first, up to 100. Pass the largest id you have seen as after to read only what is new.
{
"messages": [
{ "id": 1041, "from": "customer", "text": "Hi, are you open today?", "at": "2026-11-12T09:30:02.114Z" },
{ "id": 1042, "from": "agent", "text": "Yes, we are open until 6pm today.", "at": "2026-11-12T09:30:05.870Z" }
]
}from is customer, agent or human (a person from your team).
Errors and limits
Errors are a JSON object with a message: { "error": "…" }.
| Status | When |
|---|---|
| 400 | A field is wrong or missing (for example contact, text, messageId), or the body is not JSON. |
| 401 | The key or the secret is wrong. |
| 404 | The address is not an API channel address. |
| 405 | A method other than POST and GET. |
| 413 | The text is over 4,000 characters, or the request body is over 16,000 bytes. |
| 429 | More than 120 requests a minute on this connection (sending and reading share it). |
| 503 | The connection is paused or not connected. |
Beyond these:
- Every reply uses your credits. When credits run out, the agent stops answering and a short note goes to the customer (see Plans, credits and billing).
- Each conversation is answered at most 6 times a minute and 150 times a day. After that, messages are saved but not answered, and the channel shows a note.
- You can take over any conversation from Conversations. While a person has it,
POSTanswers withwith_a_person.
The website chat window's endpoints
The chat window is one small script that you paste into your site (see Channels). It talks to these routes, which are listed here so you can see what it does. They are for that script, and you do not need to call them yourself.
| Route | What it does |
|---|---|
GET /widget.js | The script itself. |
GET /widget/<key>/config | The window's title, greeting, colour, whether it asks for a name, and whether it is online. Public: nothing secret is in it. |
POST /widget/<key>/messages | A visitor wrote. Takes visitor (a random 32-character hex id the script keeps in the visitor's browser), text (up to 1,000 characters), and optionally name, email and phone. Answers { "ok": true }. |
GET /widget/<key>/messages?visitor=…&after=… | The visitor's messages after an id, each from visitor, team or agent, with human (a person has the chat) and online. |
The <key> here is a letter w and 24 hex characters. If you list Websites that may show it in the window's settings, a request from any other website is refused (403). A paused window answers 503.
Visitors are limited by address and by conversation, and a window has an hourly cap on messages. The numbers are kept inside the platform and may change, so build on the API channel above if you need to send messages yourself.