Developer First

Build with Kalagh

Plain HTTP and JSON, a realtime event stream, and webhooks in both directions — the same API our own app is built on.

REST API

The same HTTP endpoints our own app runs on, under /api/v1/omni — messages, conversations, contacts and automation, with one JSON envelope for every reply.

Realtime Events

A Socket.IO stream pushes every inbound message and status change to your integration the moment it happens, over a single event typed by number.

Webhooks

Both directions: a signed POST starts a workflow or playbook, and a workflow HTTP action calls your endpoint when something happens. There is no event-subscription catalogue yet.

API

// Reply into an existing conversation. `type` is a MessageType
// (1 = Text) and may be omitted; the API then defaults to Text.

POST https://api.kalagh.chat/api/v1/omni/messages/send
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json

{
  "conversationId": "0f8a3c2e-7b21-4c9e-8a1f-2d6b3e4f5a6c",
  "message": "Hello from the Kalagh API!",
  "type": 1
}

// The status line is ALWAYS 200 — success and failure arrive in the
// same envelope, so branch on isSuccess, never on the status code.
{
  "isSuccess": true,
  "status": 3,
  "data": {
    "channelId": "5c2e9d11-4a3b-4f8e-9c0d-1b2a3c4d5e6f",
    "platform": 3,
    "message": {
      "id": "9b1d7c44-2e5f-4a6b-8c1d-0f9e8d7c6b5a",
      "conversationId": "0f8a3c2e-7b21-4c9e-8a1f-2d6b3e4f5a6c",
      "providerId": "wamid.HBgLMTU1NTAxMjM0NTY...",
      "me": true,
      "type": 1,
      "status": 2,
      "content": {
        "type": 1,
        "message": "Hello from the Kalagh API!",
        "attachments": []
      },
      "createdAt": "2026-09-26T10:30:00.123Z",
      "reactions": []
    }
  },
  "message": "",
  "errorCode": 0,
  "trace": {}
}

// A failure fills the same fields. `status` says what went wrong, and
// `errorCode` narrows it where an endpoint has codes of its own:
//   4    the conversation does not exist, or you cannot see it
//   7    the body failed validation
//   9    the platform's reply window has closed (errorCode 7001 / 7002)
//   2    the provider refused the send
//   255  the token is missing, malformed or expired
{
  "isSuccess": false,
  "status": 9,
  "data": null,
  "message": "Cannot send: the messaging window for this conversation has expired.",
  "errorCode": 7001,
  "trace": {}
}

Quick start in your
Language

There is no SDK to install — Kalagh speaks plain HTTP and JSON, so your language’s own client is all you need. Every tab below does the same thing: log in, then send one message.

Python — requests
Node.js — fetch
Go — net/http
C# — HttpClient
import requests

BASE = "https://api.kalagh.chat/api/v1/omni"
CONVERSATION_ID = "0f8a3c2e-7b21-4c9e-8a1f-2d6b3e4f5a6c"
TEXT = 1  # MessageType.Text

# 1. Log in. There are no API keys: the credential is a user account,
#    and the reply carries the bearer token every other call presents.
signin = requests.post(
    f"{BASE}/account/signin",
    json={"username": "[email protected]", "password": "..."},
    timeout=30,
).json()

# Every reply is HTTP 200 — the outcome lives in the body.
if not signin["isSuccess"] or not signin["data"]["token"]:
    raise SystemExit(f"sign-in failed ({signin['status']}): {signin['message']}")

token = signin["data"]["token"]

# 2. Send a message into an existing conversation.
sent = requests.post(
    f"{BASE}/messages/send",
    headers={"Authorization": f"Bearer {token}"},
    json={
        "conversationId": CONVERSATION_ID,
        "message": "Hello from Python!",
        "type": TEXT,
    },
    timeout=30,
).json()

if not sent["isSuccess"]:
    raise SystemExit(f"send failed ({sent['status']}): {sent['message']}")

print(sent["data"]["message"]["id"])