Resources

API documentation

Version 1. All requests use HTTPS and JSON.

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" } }.

StatusCodeMeaning
400invalid_requestA field is missing or malformed. The message field explains which.
401invalid_api_keyThe key is missing, malformed, revoked or unknown.
402insufficient_balanceYour wallet can't cover the estimated cost.
409idempotency_conflictThe Idempotency-Key was reused with a different body.
422recipient_opted_outThe recipient opted out of this channel.
429rate_limitedToo many requests. Retry after the Retry-After header.
503provider_not_configuredNo 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.