Authentication
Create a key in Developers → API keys. Send it as Authorization: Bearer ks_…. Keys are displayed once; we store only a hash and cannot show them again.
Send a message
POST /api/public/v1/messages — fields: channel (sms | email), from (approved sender ID or address), to, body, and subject for email.
cURL
curl https://<your-domain>/api/public/v1/messages \-H "Authorization: Bearer ks_test_••••••••" \-H "Idempotency-Key: order-10482-shipped" \-H "Content-Type: application/json" \-d '{"channel": "sms","from": "MYSHOP","to": "+233244123456","body": "Your order #10482 has shipped."}'
Node.js
const res = await fetch("https://<your-domain>/api/public/v1/messages", {method: "POST",headers: {"Authorization": "Bearer " + process.env.KASA_API_KEY,"Idempotency-Key": "otp-" + userId,"Content-Type": "application/json",},body: JSON.stringify({ channel: "sms", from: "MYSHOP", to: "+233244123456", body: "Your code is 482910" }),});
Response · 202 Accepted
{"id": "msg_01J9Z3K8","status": "queued","segments": 1,"mode": "test"}
Errors
Errors return { "error": { "code", "message" } }.
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request | A field is missing or malformed. The message field explains which. |
| 401 | invalid_api_key | The key is missing, malformed, revoked or unknown. |
| 402 | insufficient_balance | Your wallet can't cover the estimated cost. |
| 409 | idempotency_conflict | The Idempotency-Key was reused with a different body. |
| 422 | recipient_opted_out | The recipient opted out of this channel. |
| 429 | rate_limited | Too many requests. Retry after the Retry-After header. |
| 503 | provider_not_configured | No messaging supplier is connected for this channel yet. |
Webhooks
Status events: message.accepted, message.delivered, message.failed. Outbound webhook delivery is being finalised and will be configurable in the developer portal.
Support
Signed-in customers can reach the team from their workspace. A public support channel will be listed here once it opens.