Skip to content

Guide

Send SMS from your own number

Pair a phone, create an API key, send one message and get its delivery report. Five steps, one page.

SMSKit sends each message from an Android phone and SIM you own. The recipient sees your own number. The message leaves your SIM under your carrier's normal terms. SMSKit adds no per-message fee, and your carrier's charges and limits still apply.

You need an SMSKit account, an Android phone (8.0 or newer) with a working SIM, and a backend that can make an HTTPS request. For how the pieces fit, see How it works.

1. Pair a phone

Public app downloads are currently unavailable. If the SMSKit Gateway app is already installed on your phone, carry on below.

  1. In the dashboard, open Devices, then Pair New Device.
  2. On the phone, tap Register and name the device.
  3. Scan the QR code, or enter the 6-digit pairing code, then tap Register. The code expires after 10 minutes.
  4. Tap Start service on the phone.

The phone appears under Devices, with its SIMs.

2. Create an API key

In the dashboard, open API Clients and choose + New API Client. Give it a name, then choose Create Client. Copy Key 1 when it appears. It is shown once. Keys start with sk_live_.

Send the key in the X-Api-Key header of every request. The examples below use the placeholder sk_live_your_key. Replace it with your own key and keep it out of source control.

3. Send one message

Send POST /api/v1/sms/send with the header Content-Type: application/json and a JSON body. Two fields are required: recipient, in international format, and message, up to 1,600 characters.

curl https://api.smskit.cloud/api/v1/sms/send \
  -H "X-Api-Key: sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{ "recipient": "+254712345678", "message": "Hello from SMSKit" }'

The API replies 202 Accepted at once. The message is queued, and your phone sends it. The body holds the job id and its starting status:

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

Keep the jobId. You can look the job up later with GET /api/v1/sms/{jobId}/status. See the API reference for every optional field.

4. When a request fails

A bad request gets 400 Bad Request. Here the message is empty:

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

The response is status 400 with a one-line reason:

JSON
{ "error": "Message is required." }

A missing or wrong key gets 401 Unauthorized with this body. Both shapes carry an error field to show or log:

JSON
{ "error": "Authentication required.", "statusCode": 401 }

Read the error field, such as "Message is required." or "Authentication required.". Other statuses, including 403, 422 and 429, are listed in Errors and limits.

5. Receive the delivery webhook

Register a URL with POST /api/v1/webhooks, or open Webhooks in the dashboard. Which events you can subscribe to depends on your plan.

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

The response includes the webhook's signing secret. It starts with whksec_ and is shown once, so store it.

When the carrier confirms delivery, SMSKit sends sms:delivered to your URL as a POST with a JSON body:

JSON
{
  "event": "sms:delivered",
  "deliveryId": "whd_6H9K2M5P8R1T4W7Z0C3F",
  "eventId": "evt_1D4G7K0N3Q6T9W2Z5B8E",
  "jobId": "job_7H2K9M4P1Q6R3T8V5W0X",
  "recipient": "+254712345678",
  "status": "Delivered",
  "deviceId": "dvc_3K7J2H5F8M1N4Q9R6V0W",
  "simSlot": 0,
  "timestamp": "2026-06-23T10:00:11Z"
}

The body can carry more fields than shown, such as attemptId, metadata and message. Match the job by jobId.

Check the signature

Each request carries X-SMSKit-Timestamp and X-SMSKit-Signature-256. The signature is a hex HMAC-SHA256 of the timestamp, a dot and the raw request body, keyed with your webhook secret. Compare it in constant time and reject old timestamps. Reply with any 2xx status quickly. A delivery can arrive more than once, so skip an eventId you have seen. Code for Node.js and Python is in Verifying signatures.

Explore SMSKit

Read the documentation or use your existing account. Public app downloads are currently unavailable.