Skip to content

API Reference

Base URL: https://api.smskit.cloud · Auth header: X-Api-Key: sk_live_…

Send SMS — POST /api/sms/send

Queue an SMS for delivery. Returns immediately with a job id (202 Accepted); delivery happens asynchronously on your phone.

Request body

FieldTypeReqNotes
recipientstringYesE.164 (+254712345678). Numbers without + are treated as Kenyan (+254).
messagestringYesUp to 1,600 characters. Long messages are split + reassembled.
priorityint (0–10)Higher = sent first. Default 0. Use 9–10 for OTPs.
devicesarrayTarget specific phones/SIMs. Omit to let SMSKit choose.
idempotencyKeystringDedupe retries — same key never sends twice.

Examples

curl https://api.smskit.cloud/api/sms/send \
  -H "X-Api-Key: sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{ "recipient": "+254712345678", "message": "Your code is 123456" }'

Response — 202 Accepted

{ "jobId": "job_7H2K9M4P1Q6R3T8V5W0X", "status": "Pending" }

Job status — GET /api/sms/{jobId}/status

Poll a job through its lifecycle: Pending → Assigned → Sent → Delivered, or Failed / DeadLetter.

{
  "jobId": "job_7H2K9M4P1Q6R3T8V5W0X",
  "status": "Delivered",
  "recipient": "+254712345678",
  "deviceId": "dvc_3K7J2H5F8M1N4Q9R6V0W",
  "simSlot": 0,
  "attempts": 1,
  "createdAt": "2026-06-23T10:00:00Z",
  "deliveredAt": "2026-06-23T10:00:11Z"
}

Prefer webhooks over polling for production — you get the state change pushed instantly.

Devices — GET /api/devices

List your account's phones and their SIMs — useful for building a targeting selection.

{
  "devices": [
    {
      "deviceId": "dvc_3K7J2H5F8M1N4Q9R6V0W",
      "name": "Pixel 6 — Nairobi",
      "status": "Online",
      "isEnabled": true,
      "batteryLevel": 87,
      "networkType": "LTE",
      "signalStrength": 4,
      "pendingJobCount": 0,
      "lastHeartbeatAt": "2026-06-23T10:00:05Z",
      "sims": [
        { "simSlot": 0, "carrierName": "Safaricom", "isEnabled": true, "pendingJobCount": 0 },
        { "simSlot": 1, "carrierName": "Airtel", "isEnabled": false, "pendingJobCount": 0 }
      ]
    }
  ]
}

Webhooks

Subscribe a URL and SMSKit POSTs an event the moment something happens — no polling. Events: sms:sent · sms:delivered · sms:failed · sms:received.

Register — POST /api/webhooks

curl https://api.smskit.cloud/api/webhooks \
  -H "X-Api-Key: sk_live_your_key" -H "Content-Type: application/json" \
  -d '{ "url": "https://yourapp.com/hooks/smskit", "events": ["sms:delivered", "sms:received"] }'

Other endpoints: GET /api/webhooks (list), GET /api/webhooks/{id} (detail), POST /api/webhooks/{id}/ping (send a test event).

Example payload (sms:received)

{
  "event": "sms:received",
  "eventId": "evt_5T8W1X4Y7Z0A3B6C9D2E",
  "from": "+254712345678",
  "to": "+254700000000",
  "content": "YES",
  "deviceId": "dvc_3K7J2H5F8M1N4Q9R6V0W",
  "simSlot": 0,
  "receivedAt": "2026-06-23T10:05:00Z"
}
  • • Retries with backoff + jitter on non-2xx responses.
  • • Auto-suspension — an endpoint that keeps failing is suspended (re-enable in the dashboard).
  • • Signature verification — verify the payload signature to confirm it came from SMSKit.

Two-way messaging

Inbound SMS are threaded into conversations and surfaced three ways: the sms:received webhook, the dashboard inbox, and polling with a since cursor. Replies auto-route back through the device that owns the conversation. STOP / opt-out keywords are honored automatically for compliance.

Errors & rate limits

CodeMeaningWhat to do
202 AcceptedJob queuedRead jobId + Location.
400 Bad RequestInvalid input (bad number, empty message, message > 1600, priority out of 0–10)Fix the request; the body explains what.
401 UnauthorizedMissing/invalid key, or suspended clientCheck the key and the client's status.
403 ForbiddenReferenced a device/SIM from another accountUse ids from your own GET /api/devices.
404 Not FoundUnknown job idVerify the id.
422 UnprocessableNo eligible device/SIM to sendBring a phone online or relax targeting.
429 Too Many RequestsRate limitedHonor Retry-After; back off.

Rate limits

The client API is limited per API client (currently 100 requests/hour). On 429, read Retry-After and back off. Need more throughput? It's about send capacity (more phones/SIMs), not request rate — add devices.

SDKs & samples

.NET — SMSKit.ApiClient (official reference SDK). Typed methods for send, status, and devices; handles auth, base URL, JSON, and error mapping.

{ "SmsKit": { "ServerUrl": "https://smskit.cloud", "ApiKey": "sk_live_..." } }

Other languages — the API is plain REST + JSON; the cURL/Node/Python/PHP/Go snippets above are copy-paste starting points. (Community SDKs and a CLI are on the roadmap.)