WILCYBERTEK
DOCS v2.0
Back to Gateway Dashboard Download App Get API Key
▶ Complete Platform Documentation

WilCybertek SMS Gateway

A direct, low-latency SMS platform connecting your applications to Zambia's three major mobile networks — MTN, Airtel, and Zamtel — through physical, on-premise Android GSM hardware. No international routing, no hidden relay fees. This page documents everything the platform can do: the developer REST API, the Android gateway app, the web dashboard, device management, the two-way messaging inbox, the built-in AI assistant, and wallet top-up.

MTN · Airtel · Zamtel TLS Encrypted REST / JSON Free Tier Included

Creating an Account

Every feature on this page — the API, the dashboard, the AI assistant — sits behind a free developer account.

FieldRule
name2–80 characters
emailMust contain "@" and be at least 5 characters; must be unique
passwordAt least 8 characters, with at least one uppercase letter and one digit
New accounts start with 100 free SMS credits — no card or mobile money payment required to test the platform.

Registering with an email that already has an account redirects you to /login instead of failing silently. Forgot your password? /forgot-password emails a recovery link (valid for 1 hour) to reset it — the response message is intentionally identical whether or not the email exists, so the flow can't be used to find out which emails are registered.

Android Gateway App

The WilCybertek Gateway app turns a spare Android phone into a physical SMS relay on MTN, Airtel, or Zamtel. It's the hardware behind every message this platform sends — install it before your first API call or the message never leaves QUEUED status.

You need at least one active gateway device for messages to actually be delivered. Without one, requests are accepted and stored, but nothing leaves the queue.
WilCybertek SMS Gateway v1.0.0
6.0 MB · Android 8.0+ · Updated 26 Aug 2026
Download APK

Setup

1
Install the APK
Download the APK above on the Android phone you want to use as a gateway. Enable "Install from unknown sources" if prompted — expected for apps distributed outside the Play Store.
2
Sign in with your API key
Open the app and paste your developer API key from the dashboard. This links the device to your account.
3
Point it at the server
Confirm the server URL is https://sms.wilcybertek.com, then grant the SMS and notification permissions requested.
4
Start the gateway service
Tap "Start Gateway." The device is auto-registered the first time it syncs, and appears on your Devices page within about 30 seconds.
5
Instant wake via push, polling as fallback
The app registers a push token so new jobs wake it immediately instead of waiting for the next poll cycle. If push delivery fails for any reason, the device still picks the job up on its next poll — nothing is lost.
Disable battery optimization for the app in Android settings and keep the phone plugged in. Aggressive battery savers can pause background polling/push delivery and delay messages.
Dual-SIM phones are supported. Set a default SIM slot per device on the Devices page, or override it per message with the sim_slot field (0 = SIM 1, 1 = SIM 2).
Routing rule: jobs are only dispatched to a developer's default device. If you run multiple gateway phones on one account, only the one marked "Default" on the Devices page will receive jobs — switch the default there to change which phone sends.

Quickstart

Send your first SMS in under 5 minutes.

1
Register & Get Your API Key
Create a free account. Your unique API key (format wp_live_xxxx-xxxx-...) is generated automatically and shown on your dashboard.
2
Connect a Gateway Device
Install the Android app (above) so there's hardware to actually send through.
3
Make Your First API Call
POST a JSON payload with your API key, recipient number, and message.
cURL — Quick Test
curl -X POST https://sms.wilcybertek.com/api \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "YOUR_API_KEY_HERE",
    "to":      "260977000000",
    "message": "Hello! This is my first WilCybertek SMS."
  }'
4
Top Up When You Need More Credits
You get 100 credits on signup plus 50 free credits every day. For higher volume, top up instantly via mobile money — see Wallet & Mobile Money Top-Up.

Authentication

The platform uses two independent authentication mechanisms depending on whether you're calling the API or using the web app.

API Key (developer / device endpoints)

Every API and device endpoint below resolves your account from an API key. The key can be supplied in any of these ways, checked in this order — the first one found wins:

PriorityLocationExample
1X-API-KeyHTTP header (recommended)
2api_keyJSON body field
3api_keyURL query string
4api_keyForm-encoded body field
HTTP Header — Recommended
X-API-Key: wp_live_a1b2c3d4-e5f6-...
Your API key can be regenerated any time from the dashboard (Regenerate Key button). Doing so immediately invalidates the old key everywhere — update every integration and the gateway app before rotating in production.

Session Cookie (web dashboard)

Logging in at /login issues a signed session cookie. All dashboard pages (Dashboard, Devices, Messages, Send SMS, AI Assistant) and their POST actions run behind this session — see Security Model for CSRF details. Session-based routes do not accept an API key.

Send SMS

The core endpoint. Queues one SMS for delivery through your default (or a specified) gateway device.

POST/apiRequires API key

Accepts either application/json or application/x-www-form-urlencoded.

Body Parameters

FieldTypeDescription
tostringrequiredRecipient number. Auto-normalized to 260XXXXXXXXX — see Phone Number Formatting.
messagestringrequiredSMS body. Max 1,600 characters.
device_idstringoptionalSend from a specific gateway device instead of your account default.
sim_slotintoptional0 = SIM 1, 1 = SIM 2. Falls back to your account/device default.
Request — JSON
POST /api HTTP/1.1
Host: sms.wilcybertek.com
Content-Type: application/json
X-API-Key: wp_live_xxxx-xxxx-...

{
  "to": "260977000000",
  "message": "Your order #4821 has shipped.",
  "sim_slot": 0
}
Response — 200 OK
{
  "success": true,
  "id": 4821,
  "status": "QUEUED"
}
Each successful send debits exactly 1 credit from your balance (skipped entirely for unlimited accounts). If a message later fails delivery, the credit is automatically refunded to your balance.

Message Status Values

Every queued message moves through this lifecycle. You'll see these values in your dashboard logs and in /update_status.php reports.

StatusMeaning
QUEUEDAccepted, waiting for a gateway device to pick it up.
SENDINGA device has claimed the job and is dispatching it via GSM.
SENTConfirmed sent by the device.
DELIVEREDConfirmed delivered (when the network/device reports a delivery receipt).
FAILEDDelivery failed — the spent credit is automatically refunded.
PROCESSINGShown on the dashboard for jobs mid-flight; requeue-able if stuck.

Register a Device

Registers (or updates) a gateway device under your account. The official Android app calls this automatically — you only need it directly if you're building a custom gateway client.

POST/register_device.phpRequires API key
FieldTypeDescription
device_idstringrequiredStable unique identifier for the phone (e.g. Android ID).
device_namestringoptionalFriendly label shown on the Devices page.
sim_slotsintoptionalNumber of active SIM slots. Defaults to 1.
The first device you ever register is automatically set as your account's default device.
Response — 200 OK
{ "success": true }

Push Token Registration

Registers a device's push (Firebase Cloud Messaging) token so it can be woken instantly when a new job is queued, instead of waiting for its next poll.

POST/register_fcm_token.phpRequires API key
FieldTypeDescription
device_idstringrequiredMust match a registered device.
fcm_tokenstringrequiredPush token issued by Firebase on the device.
This can be called before /register_device.php finishes — the token is safely stored either way and linked up automatically. Push is best-effort: if it's ever unavailable, normal polling still delivers the job.

Job Polling (gateway devices)

Used by a gateway device to ask "do you have a message for me to send?" This is how the Android app fetches queued jobs; build against it directly only if you're writing your own gateway client.

GET/get_pending_sms.php?device_id=...POST also accepted
FieldTypeDescription
device_idstringrequiredThe polling device's ID (accepts device as an alias).
api_keystringoptionalOnly needed the very first time a brand-new device polls, to auto-register it.

Only the account's default device is ever handed a job — this prevents two phones on the same account from racing for the same message.

Response — job found
{
  "status": "found",
  "id": "4821",
  "phone": "260977000000",
  "message": "Your order #4821 has shipped.",
  "sim_slot": 0
}
Response — nothing queued
{ "status": "none" }

Delivery Status Report

Called by a gateway device after it attempts to send, to report the outcome back to the platform.

POST/update_status.php
FieldTypeDescription
idintrequiredThe message id returned by /api or fetched via job polling.
statusstringrequiredSENT, FAILED, or DELIVERED. Anything else is recorded as FAILED.
device_idstringoptionalReporting device, for the audit trail.
Reporting FAILED on a message automatically refunds 1 credit to the developer's balance (unless the account is unlimited).

Receive Inbound SMS

Called by the gateway app the moment it receives an SMS on the phone, forwarding it into your inbox in real time (single message — see the next section for bulk sync).

POST/receive_sms.phpRequires API key
FieldTypeDescription
senderstringrequiredNumber that sent the SMS.
messagestringrequiredSMS body.
device_idstringoptionalReceiving device.
sim_slotintoptionalWhich SIM received it.

Bulk Message Sync

Bulk-syncs a batch of native SMS threads (inbox and/or sent) from the phone into the platform's Messages view. /sync_inbox.php and /sync_messages.php are aliases — both run the exact same handler.

POST/sync_inbox.phpRequires API key
POST/sync_messages.phpRequires API key · alias
FieldTypeDescription
device_idstringrequiredSyncing device (auto-registered if unseen before).
phone_namestringoptionalFriendly device name if not already set.
messagesarrayrequiredArray of message objects (form field messages as a JSON string, or a top-level JSON array field — both accepted).

Message Object

FieldTypeDescription
idstringNative message ID on the device (used to de-duplicate re-syncs).
addressstringOther party's number.
bodystringMessage text.
dateintEpoch milliseconds.
readint1 if read, 0 otherwise.
boxstringinbox or sent.
Response — 200 OK
{ "success": true, "inserted": 14 }
Duplicate syncs are safe — messages are keyed by (device_id, native id, box) and re-inserts are silently skipped.

Dashboard

Your account's home base at /dashboard — everything below is a real, working feature, not a placeholder.

Delivery Stats
Live totals for sent, failed, queued, and processing messages, plus an overall delivery rate percentage.
Paginated Message Log
Your last messages (15 per page) with recipient, truncated message preview, device, status, and timestamp.
Regenerate API Key
POST /dashboard/regen-key — instantly rotates your key and logs the action (with your IP) to the account's security log.
Clear Logs
POST /dashboard/clear-logs — permanently wipes your API log history. This does not affect your credit balance.
Requeue Stuck Messages
POST /dashboard/requeue — resets any FAILED, PENDING, or PROCESSING message back to QUEUED for another delivery attempt.
Daily Free Top-Up
Non-unlimited accounts automatically receive +50 credits the first time they load the dashboard each day.

Wallet & Mobile Money Top-Up

Buy more SMS credits instantly from the dashboard using MTN, Airtel, or Zamtel Mobile Money — processed via the Lenco payments network.

PlanAmountCredits
StarterK50625
BasicK1001,250
GrowthK2002,500
ProK3003,750
BusinessK5006,250
EnterpriseK1,00012,500

Every plan works out to the same rate: 1 credit ≈ K0.08. Custom amounts are accepted too, with a K50 minimum per top-up.

1
Choose an amount and enter your mobile money number
Pick MTN, Airtel, or Zamtel as the operator; your number is normalized automatically.
2
Approve the collection prompt on your phone
A mobile money authorization request is pushed to your device via Lenco.
3
Credits land automatically
Once payment is confirmed, your balance updates without needing to refresh — the dashboard polls the transaction status for you.
Payment confirmations are pushed to the server by Lenco's webhook the moment a transaction clears — you don't need to do anything beyond approving the prompt on your phone.

Devices Page

Manage every gateway phone connected to your account at /devices.

Set Default Device & SIM
Choose which phone (and which SIM slot on it) receives new jobs by default.
Enable / Disable a Device
Temporarily pause a device without deleting it — disabled devices are excluded from the manual Send SMS device list.
Per-Device Sent Count
See how many messages each device has successfully sent.
Last Seen
Timestamp of the device's most recent poll or sync — the quickest way to tell if a phone has gone offline or lost connectivity.

Messages & Inbox

A two-way messaging view at /messages — not just an outbox.

Inbox & Sent Tabs
Browse everything synced from your devices via Receive Inbound SMS and Bulk Message Sync, paginated 30 at a time.
Filter by Device
Narrow the thread list down to a single gateway phone.
Reply From the Web
POST /messages/reply queues an outbound reply through the specified device — the same underlying queue the API and manual Send SMS form use.

Send SMS (Web Form)

A manual, one-off sending form at /send-sms for testing or ad-hoc messages without touching the API — useful for verifying a device is wired up correctly.

Lets you pick a specific active device and SIM slot per send, and debits the same 1-credit-per-message balance as the API.

AI Assistant

A built-in chat assistant, available to logged-in accounts.

POST/aiRequires session login
FieldTypeDescription
messagestringrequiredYour message to the assistant.
This is a dashboard convenience feature reached through your logged-in session — it authenticates differently from the rest of the API and is not callable with your API key. It's for use from the web app, not for integrating into third-party apps.

Supported Networks

All three major Zambian mobile networks are supported for both sending and mobile money top-up.

MTN Zambia
076 / 077 / 078
Airtel Zambia
095 / 096 / 097
Zamtel
095 / 097

Phone Number Formatting

Recipient numbers are normalized automatically to the 260XXXXXXXXX international format — non-digit characters are stripped first.

You sendNormalized toRule
9770000002609770000009 digits → prefix with 260
0977000000260977000000Leading 0 + 10 digits → drop the 0, prefix with 260
260977000000260977000000Already in international format → unchanged

Rate Limits

Rate limits currently apply to authentication endpoints only, tracked per client IP address. The /api send endpoint and device endpoints are not IP-rate-limited — your SMS balance is the natural throttle.

Login attempts
5 / 5 min
Registration attempts
3 / 10 min
Password reset requests
3 / 10 min

Error Reference

Actual error payloads returned by the API and device endpoints — every response is JSON with an error field describing what went wrong.

HTTPerrorCause
405POST requiredWrong HTTP method used.
401Invalid API keyKey missing, mistyped, or revoked (e.g. after a regeneration).
402Insufficient SMS balanceBalance is 0 and the account isn't unlimited.
400to and message are requiredMissing recipient or body on /api.
400message too longBody exceeds 1,600 characters.
400device_id requiredMissing on /register_device.php.
400device_id and fcm_token requiredMissing on /register_fcm_token.php.
400sender and message requiredMissing on /receive_sms.php.
400invalid messages JSONMalformed payload on /sync_inbox.php / /sync_messages.php.
500Failed to queue messageDatabase error while inserting the job — rare, safe to retry.

Security Model

Password Hashing
Passwords are hashed with bcrypt before storage — never stored or logged in plaintext.
CSRF Protection
All classic form-based dashboard POSTs (login, register, password reset, key regen, clear logs, requeue, refill, device settings) require a matching csrf_token tied to your session.
API Key Scope
Your API key authorizes sending, device management, and message sync — it does not grant access to the web dashboard session.
Anti-Enumeration
Password reset always returns the same message regardless of whether the email exists, so the endpoint can't be used to discover registered accounts.

cURL

bash
curl -X POST https://sms.wilcybertek.com/api \
  -H "X-API-Key: wp_live_xxxx-xxxx-..." \
  -H "Content-Type: application/json" \
  -d '{"to":"260977000000","message":"Hello from cURL"}'

JavaScript (fetch)

javascript
const res = await fetch("https://sms.wilcybertek.com/api", {
  method: "POST",
  headers: {
    "X-API-Key": "wp_live_xxxx-xxxx-...",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    to: "260977000000",
    message: "Hello from JavaScript"
  })
});
const data = await res.json();
console.log(data);

Python

python
import requests

resp = requests.post(
    "https://sms.wilcybertek.com/api",
    headers={"X-API-Key": "wp_live_xxxx-xxxx-..."},
    json={"to": "260977000000", "message": "Hello from Python"},
)
print(resp.json())

PHP

php
<?php
$ch = curl_init("https://sms.wilcybertek.com/api");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "X-API-Key: wp_live_xxxx-xxxx-...",
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => json_encode([
        "to" => "260977000000",
        "message" => "Hello from PHP",
    ]),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;