WikiTeq SMS API
Send transactional and bulk SMS from your own application, track delivery in real time, and monitor your credit balance — all with simple HTTP requests.
Overview
Everything is served from a single base URL and works with plain HTTPS. Every endpoint accepts GET query strings or a POST JSON body.
1Quick start
Go from zero to a delivered message in three steps.
- Get your credentials. You need your
apikey,partnerIDand an approvedshortcode(Sender ID) from your WikiTeq SMS account. - Send a request. Call
/api/services/sendsmswith the parameters below. - Track it. Use the returned
messageidto fetch a delivery report, or set a callback URL to receive it automatically.
curl -X POST https://sms.wikiteq.co.ke/api/services/sendsms \
-H "Content-Type: application/json" \
-d '{
"apikey": "YOUR_API_KEY",
"partnerID": "YOUR_PARTNER_ID",
"message": "Hello from WikiTeq SMS!",
"shortcode": "YOUR_SHORTCODE",
"mobile": "2547XXXXXXXX"
}'const axios = require('axios');
axios.post('https://sms.wikiteq.co.ke/api/services/sendsms', {
apikey: 'YOUR_API_KEY',
partnerID: 'YOUR_PARTNER_ID',
message: 'Hello from WikiTeq SMS!',
shortcode: 'YOUR_SHORTCODE',
mobile: '2547XXXXXXXX'
}, { headers: { 'Content-Type': 'application/json' } })
.then(res => console.log(res.data))
.catch(err => console.error(err.response?.data || err.message));<?php
$payload = [
'apikey' => 'YOUR_API_KEY',
'partnerID' => 'YOUR_PARTNER_ID',
'message' => 'Hello from WikiTeq SMS!',
'shortcode' => 'YOUR_SHORTCODE',
'mobile' => '2547XXXXXXXX',
];
$ch = curl_init('https://sms.wikiteq.co.ke/api/services/sendsms');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($ch);
curl_close($ch);import requests
r = requests.post(
"https://sms.wikiteq.co.ke/api/services/sendsms",
json={
"apikey": "YOUR_API_KEY",
"partnerID": "YOUR_PARTNER_ID",
"message": "Hello from WikiTeq SMS!",
"shortcode": "YOUR_SHORTCODE",
"mobile": "2547XXXXXXXX",
},
timeout=30,
)
print(r.json())2Authentication
Credentials are sent with every request, either as query parameters (GET) or in the JSON body (POST).
| Credential | Description |
|---|---|
apikey | Your valid API key. |
partnerID | Your Partner ID. |
shortcode | Your assigned Sender ID / short code, required when sending messages. |
POST over GET so keys don't end up in server logs.3Send SMS
Send a message to a single number via GET, or to one or multiple numbers via POST. For multiple numbers, pass them as a comma-separated string (maximum 1000 numbers per request).
Parameters
| Parameter | Description | |
|---|---|---|
apikey | Your valid API key. | REQUIRED |
partnerID | Your Partner ID. | REQUIRED |
message | The message text, URL-encoded (GSM7). | REQUIRED |
shortcode | Sender ID / shortcode. | REQUIRED |
mobile | Recipient mobile number. For POST, multiple numbers can be comma-separated (max 1000). | REQUIRED |
timeToSend | Schedule the message. A valid date string that resolves to a Unix timestamp (e.g. "2019-09-01 18:00") or the Unix timestamp itself. | OPTIONAL |
timeToSend to your POST request to deliver the message at a later time.Example request
https://sms.wikiteq.co.ke/api/services/sendsms?apikey={{apikey}}&partnerID={{partnerID}}&message={{message}}&shortcode={{shortcode}}&mobile={{mobile}}{
"apikey": "{{apikey}}",
"partnerID": "{{partnerID}}",
"message": "{{message}}",
"shortcode": "{{shortcode}}",
"mobile": "{{mobile}}",
"timeToSend": "2019-09-01 18:00" // optional
}const axios = require('axios');
axios.get('https://sms.wikiteq.co.ke/api/services/sendsms', {
params: {
apikey: '{{apikey}}',
partnerID: '{{partnerID}}',
message: '{{message}}',
shortcode: '{{shortcode}}',
mobile: '{{mobile}}'
}
}).then(response => console.log(response.data))
.catch(error => console.error(error));const axios = require('axios');
axios.post('https://sms.wikiteq.co.ke/api/services/sendsms', {
apikey: '{{apikey}}',
partnerID: '{{partnerID}}',
message: '{{message}}',
shortcode: '{{shortcode}}',
mobile: '{{mobile}}'
}, {
headers: { 'Content-Type': 'application/json' }
}).then(response => console.log(response.data))
.catch(error => console.error(error));Responses
{
"responses": [
{
"response-code": 200,
"response-description": "Success",
"mobile": xxxxxxxxxxxxx,
"messageid": "xxxxxxxxxxx",
"networkid": 1
}
]
}{
"response-code": 1006,
"response-description": "Invalid credentials"
}4Send bulk
Send up to 1000 unique messages in one request. Each item can have its own recipient and message content.
partnerID, apikey and shortcode must be the same for every object in smslist. Any mismatch defaults to the credentials in the first object.Body fields
| Field | Description |
|---|---|
count | The number of items in smslist. |
smslist[] | Array of message objects (max 1000). |
partnerID / apikey / shortcode | Your credentials and sender ID (identical across all items). |
pass_type | Set to "plain". |
clientsmsid | Your own dynamic identifier for the message. It is echoed back in the response so you can match results to your records. |
mobile | Recipient mobile number. |
message | Message text for this recipient. |
Example request
{
"count": {{count}},
"smslist": [
{
"partnerID": "{{partnerID}}",
"apikey": "{{apikey}}",
"pass_type": "plain",
"clientsmsid": {{clientsmsid1}},
"mobile": "{{mobile1}}",
"message": "{{message1}}",
"shortcode": "{{shortcode}}"
},
{
"partnerID": "{{partnerID}}",
"apikey": "{{apikey}}",
"pass_type": "plain",
"clientsmsid": {{clientsmsid2}},
"mobile": "{{mobile2}}",
"message": "{{message2}}",
"shortcode": "{{shortcode}}"
}
]
}const axios = require('axios');
const payload = {
count: {{count}},
smslist: [
{
partnerID: "{{partnerID}}",
apikey: "{{apikey}}",
pass_type: "plain",
clientsmsid: {{clientsmsid1}},
mobile: "{{mobile1}}",
message: "{{message1}}",
shortcode: "{{shortcode}}"
},
{
partnerID: "{{partnerID}}",
apikey: "{{apikey}}",
pass_type: "plain",
clientsmsid: {{clientsmsid2}},
mobile: "{{mobile2}}",
message: "{{message2}}",
shortcode: "{{shortcode}}"
}
]
};
axios.post('https://sms.wikiteq.co.ke/api/services/sendbulk', payload, {
headers: { 'Content-Type': 'application/json' }
})
.then(response => console.log(response.data))
.catch(error => console.error(error));Responses
{
"responses": [
{
"response-code": 200,
"response-description": "Success",
"mobile": "xxxxxxxx",
"messageid": "xxxxxxxx",
"clientsmsid": 1234,
"networkid": 1
},
{
"response-code": 200,
"response-description": "Success",
"mobile": "xxxxxxxx",
"messageid": "xxxxxxxx",
"clientsmsid": 1235,
"networkid": 1
}
]
}{
"response-code": 1006,
"response-description": "Invalid credentials"
}5Delivery reports
Check the status of a sent message using the messageid returned when it was sent — or have reports pushed to your server automatically.
| Parameter | Description |
|---|---|
apikey | Your valid API key. |
partnerID | Your Partner ID. |
messageID | Message ID returned when the SMS was sent. |
https://sms.wikiteq.co.ke/api/services/getdlr?apikey={{apikey}}&partnerID={{partnerID}}&messageID={{messageID}}{
"apikey": "{{apikey}}",
"partnerID": "{{partnerID}}",
"messageID": "{{messageID}}"
}{
"response-code": 200,
"message-id": "xxxxxxxxx",
"response-description": "Success",
"delivery-status": 32,
"delivery-description": "DeliveredToTerminal",
"delivery-tat": "00:02:30",
"delivery-networkid": 1,
"delivery-time": "2024-11-01 11:15:32"
}{
"response-code": 1009,
"response-description": "No dlr"
}Real-time callbacks (recommended)
Configure your callback URL:
- Log into your SMS account.
- Click Partners in the left menu.
- Select the account you want to configure.
- Toggle the API option.
- Scroll down to Callback URL and enter the endpoint where reports should be sent.
- Click Save.
Callback payload
When a delivery report is available, a request is sent to your callback URL with this payload:
{
"description": "DeliveredToTerminal",
"messageid": "1889191",
"timeTaken": "22s", // turnaround time for message delivery
"timestamp": "2025-09-12 10:16:10"
}messageid. A delivery-status of 32 means DeliveredToTerminal.6Account balance
Check your available credit before sending, so campaigns never fail for lack of balance.
| Parameter | Description |
|---|---|
apikey | Your valid API key. |
partnerID | Your Partner ID. |
https://sms.wikiteq.co.ke/api/services/getbalance?apikey={{apikey}}&partnerID={{partnerID}}{
"apikey": "{{apikey}}",
"partnerID": "{{partnerID}}"
}{
"response-code": 200,
"credit": "545.00",
"partner-id": "xxxxx"
}{
"response-code": 1006,
"response-description": "Invalid credentials"
}7Response codes
Every response includes a response-code and a human-readable response-description.
| Code | Description | Meaning |
|---|---|---|
| 200 | Success | Request accepted and processed. |
| 1006 | Invalid credentials | Check your apikey and partnerID. |
| 1009 | No dlr | No delivery report is available yet for that message ID. |
Delivery statuses
| Status | Description |
|---|---|
| 32 | DeliveredToTerminal — the message reached the recipient's handset. |
Your account may return additional codes and statuses. Always handle unknown values gracefully and log the full response.
8Best practices
- URL-encode the
messagewhen usingGET, and use GSM7 characters to keep messages within a single SMS segment. - Use POST for production traffic and for anything with more than one recipient.
- Use
/sendbulkwith a uniqueclientsmsidper item when each recipient gets personalised content. - Prefer callbacks over polling
/getdlrto receive delivery reports in real time. - Check your balance with
/getbalancebefore large campaigns. - Store the
messageidfrom every response so you can reconcile delivery later. - Protect your API key: server-side only, rotated if exposed.