REST API reference
Official Cloud API · self-hosted · zero markup — you pay Meta directly.
The Klaros API is a thin, official layer over the WhatsApp Cloud API running on your own deployment. Send messages and templates, read conversations and threads, and list approved templates — with your data on your infrastructure and no per-message markup.
Base URL — your deployment, e.g.
https://<your-deployment>/api/v1
Auth — send your account API key as a Bearer token:
Authorization: Bearer uni_live_…. Machine-readable spec:
openapi.json.
Quickstart — send your first message
Three steps to your first send
- Get your API key. In the Klaros dashboard, go to Settings → API Keys and copy your
uni_live_…key. - Set your base URL. Your deployment URL, e.g.
https://your-deployment.example.com. - Send a template. Outside the 24h window, you need an approved template. Inside it, freeform text works too.
# Set your credentials export BASE="https://your-deployment.example.com" export KLAROS_API_KEY="uni_live_…" # Send a template message curl -X POST "$BASE/api/v1/messages" \ -H "Authorization: Bearer $KLAROS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"to":"15551234567","templateName":"hello_world","templateLang":"en_US"}'
The response includes waMessageId and sentStatus. Check delivery via webhooks or the inbox.
Send a message
POST /messages
Send freeform text (only inside the 24-hour customer-service window) or an
approved template (any time). Outside the window a text send returns
409 with needsTemplate: true. Add an optional
from (a phoneNumberId from
/numbers) to send from a specific line; omit it to use your default.
# Text (inside the 24h window) curl -X POST "$BASE/api/v1/messages" \ -H "Authorization: Bearer $KLAROS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"to":"15551234567","text":"Thanks for reaching out!"}' # Approved template, sent from a specific line curl -X POST "$BASE/api/v1/messages" \ -H "Authorization: Bearer $KLAROS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"to":"15551234567","from":"123456789012345","template":{"name":"order_update","language":"en_US"}}'
List conversations
GET /conversations
Most-recent-first, with each conversation's 24h-window state. Query: limit (max 200).
curl "$BASE/api/v1/conversations?limit=50" \ -H "Authorization: Bearer $KLAROS_API_KEY"
Get a conversation thread
GET /conversations/{phone}/messages
Full thread, oldest → newest. phone is E.164 digits (no +).
curl "$BASE/api/v1/conversations/15551234567/messages" \ -H "Authorization: Bearer $KLAROS_API_KEY"
List templates
GET /templates
Your WABA's message templates with approval status and category.
curl "$BASE/api/v1/templates" \ -H "Authorization: Bearer $KLAROS_API_KEY"
Numbers (lines)
GET /numbers
Every WhatsApp line connected to your workspace — its phoneNumberId,
friendly label, WABA, and which one is the sending
default. Use a line's phoneNumberId as
from when sending. One business, many numbers, one workspace.
curl "$BASE/api/v1/numbers" \ -H "Authorization: Bearer $KLAROS_API_KEY"
Account & connected number
GET /me
Your account, plan, and the connected WhatsApp number / WABA.
curl "$BASE/api/v1/me" \ -H "Authorization: Bearer $KLAROS_API_KEY"
Webhooks
Register an https endpoint and Klaros POSTs a signed event the moment
something happens on your number — perfect for n8n, Zapier, or your own backend. Events:
message.received, message.status,
message.optout. Failed deliveries retry automatically with backoff.
POST /webhooks
Register an endpoint. The signing secret is returned once — store it to
verify the X-Klaros-Signature header. Omit events to receive all.
curl -X POST "$BASE/api/v1/webhooks" \ -H "Authorization: Bearer $KLAROS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url":"https://example.com/klaros/webhook","events":["message.received","message.optout"]}' # → 201 { "data": { "id": "…", "secret": "whsec_…", … } } (the secret is shown only here) # List / inspect deliveries / delete curl "$BASE/api/v1/webhooks" -H "Authorization: Bearer $KLAROS_API_KEY" curl "$BASE/api/v1/webhooks/$ID/deliveries" -H "Authorization: Bearer $KLAROS_API_KEY" curl -X DELETE "$BASE/api/v1/webhooks/$ID" -H "Authorization: Bearer $KLAROS_API_KEY"
Event payload & verifying the signature
Each delivery is a JSON body { id, type, created_at, data } with these headers:
X-Klaros-Event, X-Klaros-Delivery, and
X-Klaros-Signature: sha256=<hmac>. The HMAC is SHA-256 of the
raw request body, keyed by your subscription secret. Verify it before trusting the event:
// Node.js — compute and compare import crypto from 'node:crypto'; function verify(rawBody, header, secret) { const expected = 'sha256=' + crypto.createHmac('sha256', secret) .update(rawBody).digest('hex'); return crypto.timingSafeEqual(Buffer.from(header), Buffer.from(expected)); } // Example message.received body { "id": "…", "type": "message.received", "created_at": "2026-06-25T…Z", "data": { "from": "15551234567", "text": "Hi!", "wa_message_id": "wamid…" } }
Need an SDK for your language, or a custom event? Talk to us.