Bulk SMS API Documentation
Send Single, Bulk, Unicode, Dynamic (mail-merge) and OTP SMS directly from your website or software over a plain HTTP request — no SDK and no OAuth handshake required. This is the exact same API that powers our own web portal, fully compatible with PHP, ASP, .NET, JSP, C# and Java integrations. Prefer to explore it visually first? Browse our full Postman collection — every endpoint on this page is pre-built there, ready to run with your own credentials.
Local traffic only: this channel is strictly for terminating local/Pakistani-origin companies, products and services. Terminating traffic on behalf of any international entity, directly or indirectly, is treated as a violation of these terms and can lead to legal action for damages or losses incurred.
Account Verification Required
Before your Sender ID can be approved and activated, account verification is required. Verify your account to display your own message; otherwise, our default demo text will be appended.
- CNIC
- Face ID
- Legal agreement on letterhead
- NTN (National Tax Number)
Plain HTTP GET/POST
No SDK required — call the endpoint from any language that can make an HTTP request.
Single & Bulk sends
Send to one recipient or a comma-separated list in exactly the same call.
Dynamic mail-merge
Upload a spreadsheet and send a uniquely personalized message to every row in one call.
Unicode-ready
Send emoji and regional-script text by setting type=unicode.
JSON & XML output
Add format=json or format=xml for a structured response.
Fixed-SMS & OTP templates
Fill a pre-approved template with template_id and a small JSON payload.
Getting Started
From signup to your first delivered SMS in a few minutes.
Create your free account
Sign up with your name, mobile number and email — no paperwork to get started.
Get your Sender ID approved
Verify your account for the route your business needs — Semi Branded, Branded or Short Code (OTP) SMS.
Grab your API key
Copy your unique api_key from your dashboard's Profile page — it authenticates every API call you make.
Call the API
Hit api/sms.php with your API key, sender ID, recipient and message.
Track delivery & balance
Poll delivery.php for a message's status and balance.php for your remaining credit.
Authentication
Every request is authenticated with a single api_key parameter. The older username / password login-pair auth is deprecated — use api_key on every call shown on this page.
Where to find it
Log in to your dashboard and open Profile → API Key to copy your unique api_key.
Sending it
Pass api_key as a plain request parameter on every call, via GET query string or POST body:
Treat your api_key like a password. Never expose it in client-side JavaScript, public repositories, or mobile app bundles — always call this API from your own backend server.
Sender ID (Masking)
The sender parameter is the name recipients see as the message sender. It must match a Sender ID that's been approved for your account.
| Route | Sender ID |
|---|---|
| Simple SMS | Sent from a pre-approved shared name such as SMS Alert — instant approval. |
| Branded SMS | Your own company or brand name — requires a one-time mask approval. |
| Short Code / OTP | Delivered via our dedicated short code route for time-critical codes — default short code is 8584. |
Base URL & Endpoints
There's one endpoint per operation — sending, dynamic/mail-merge sending, checking a delivery report, and checking your balance.
| Purpose | Endpoint |
|---|---|
| Send SMS (single, bulk, unicode, fixed/OTP) | https://sendpk.com/api/sms.php |
| Dynamic / personalized SMS from a file | https://sendpk.com/api/personalised.php |
| Delivery report | https://sendpk.com/api/delivery.php |
| Check balance | https://sendpk.com/api/balance.php |
api_key out of server access logs in production.
Request Parameters
Our docs are friendly enough that you don't need deep developer knowledge to integrate — here's every parameter the sms.php endpoint accepts.
| Parameter | Description |
|---|---|
api_key required | Your unique API key, from Profile → API Key. |
sender required | Your approved Sender ID / brand name. |
mobile required | Recipient mobile number, or a comma-separated list for bulk sends, e.g. 923001234567,923101234567. |
message required | The message text. For Fixed-SMS/OTP templates, pass a JSON string of your template's variables instead, e.g. {"name":"Umair","pin":"456723"} — see Fixed / OTP SMS. |
network optional | One of Jazz, Zong, Ufone, Telenor. Use it to route SMS on ported/MNP numbers, or to force a specific operator. |
type optional | Set to unicode to send emoji or non-Latin script text. |
template_id optional | Your approved Fixed-SMS/OTP template ID. |
format optional | Set to json, xml or plain (case-insensitive) to choose the response format. |
The Dynamic / Personalized SMS endpoint accepts its own url and duplicate parameters instead of mobile — see its dedicated section below.
Response Format
By default the API replies with a short plain-text line. Add format=json or format=xml on any request to get the same status/ID pair back as structured data instead.
OK Successful response
The number after ID: is your unique message ID — save it if you plan to check the delivery report later.
Status Codes
Every response starts with OK on success, or a numeric code that tells you exactly what went wrong.
| Code | Meaning |
|---|---|
| OK | Message was successfully accepted for delivery. |
1 | API key is invalid, expired, or your account is disabled. |
2 | API key is empty. |
3 | Reserved (legacy code, unused with api_key auth). |
4 | Sender ID is empty. |
5 | Recipient is empty. |
6 | Message is empty. |
7 | Invalid recipient number. |
8 | Insufficient credit — top up your balance to continue sending. |
9 | SMS rejected. |
Overview
One core endpoint, several ways to use it — plus a dedicated endpoint for file-based mail-merge sending. Pick the flavor that matches what you're sending.
Fixed / OTP SMS
Per PTA guidelines, SMS falls into two categories: transactional (critical/informational
messages and OTPs) and promotional (marketing content). Fixed-SMS templates keep your
transactional content pre-approved and PTA-compliant — only the variable parts change per message.
Variables are written as #variable_name# in the approved template; you fill them in with a
JSON object of matching keys.
Video Tutorial
Prefer to watch it in action? This walkthrough covers Fixed / OTP SMS end-to-end.
Creating a template
Log in to your dashboard
Open the SMS Templates section from your account.
Open Fixed-SMS-Templates
Found in the top-right corner of the SMS Templates page.
Submit your content
Write your message with #variable_name# placeholders for anything that changes per recipient.
Wait for approval
Once approved you'll get a template_id — ready to use immediately.
Required Parameters
| Parameter | Description |
|---|---|
template_id required | Your approved Fixed-SMS/OTP template ID. |
message required | JSON string of variable values, e.g. {"name":"Umair","pin":"456723"}. |
Request Example
GET https://sendpk.com/api/sms.php?api_key=3f9a2b7c6e1d4c2a9b0e8d5f1a2b3c4d&sender=8584&mobile=923001234567&template_id=APPROVED_ID&message={"name":"Umair","pin":"456723"}
Short Code / OTP templates typically send from a shared short code (e.g. 8584) rather than a custom brand name. Read the full walkthrough in our Fixed-SMS Templates guide.
Send Single SMS
Sends one message to one recipient.
Request Example
GET https://sendpk.com/api/sms.php?api_key=3f9a2b7c6e1d4c2a9b0e8d5f1a2b3c4d&sender=YourBrand&mobile=923001234567&message=Your table is ready, see you soon!
Response Example
curl -G 'https://sendpk.com/api/sms.php' \
-d 'api_key=3f9a2b7c6e1d4c2a9b0e8d5f1a2b3c4d' \
-d 'sender=YourBrand' \
-d 'mobile=923001234567' \
-d 'message=Your table is ready, see you soon!'<?php
$post = http_build_query([
'api_key' => '3f9a2b7c6e1d4c2a9b0e8d5f1a2b3c4d',
'sender' => 'YourBrand',
'mobile' => '923001234567',
'message' => 'Your table is ready, see you soon!',
]);
$result = file_get_contents('https://sendpk.com/api/sms.php?' . $post);
if (strpos($result, 'OK') === 0) {
echo 'Sent! ' . $result;
} else {
echo 'Error code: ' . $result;
}const params = new URLSearchParams({
api_key: '3f9a2b7c6e1d4c2a9b0e8d5f1a2b3c4d',
sender: 'YourBrand',
mobile: '923001234567',
message: 'Your table is ready, see you soon!',
});
const res = await fetch('https://sendpk.com/api/sms.php?' + params);
const text = await res.text();
console.log(text); // e.g. "OK ID:29346"import requests
response = requests.get('https://sendpk.com/api/sms.php', params={
'api_key': '3f9a2b7c6e1d4c2a9b0e8d5f1a2b3c4d',
'sender': 'YourBrand',
'mobile': '923001234567',
'message': 'Your table is ready, see you soon!',
})
print(response.text) # e.g. "OK ID:29346"Send Bulk SMS
Sends the same message to multiple recipients in a single call. Separate numbers with a comma — duplicates and invalid numbers are filtered automatically.
Request Example
GET https://sendpk.com/api/sms.php?api_key=3f9a2b7c6e1d4c2a9b0e8d5f1a2b3c4d&sender=YourBrand&mobile=923001234567,923101234567&message=Flash Sale! 30% off everything today only.
Response Example
curl -G 'https://sendpk.com/api/sms.php' \
-d 'api_key=3f9a2b7c6e1d4c2a9b0e8d5f1a2b3c4d' \
-d 'sender=YourBrand' \
-d 'mobile=923001234567,923101234567' \
-d 'message=Flash Sale! 30% off everything today only.'<?php
$post = http_build_query([
'api_key' => '3f9a2b7c6e1d4c2a9b0e8d5f1a2b3c4d',
'sender' => 'YourBrand',
'mobile' => '923001234567,923101234567',
'message' => 'Flash Sale! 30% off everything today only.',
]);
$result = file_get_contents('https://sendpk.com/api/sms.php?' . $post);
echo $result;const params = new URLSearchParams({
api_key: '3f9a2b7c6e1d4c2a9b0e8d5f1a2b3c4d',
sender: 'YourBrand',
mobile: '923001234567,923101234567',
message: 'Flash Sale! 30% off everything today only.',
});
const res = await fetch('https://sendpk.com/api/sms.php?' + params);
console.log(await res.text());import requests
response = requests.get('https://sendpk.com/api/sms.php', params={
'api_key': '3f9a2b7c6e1d4c2a9b0e8d5f1a2b3c4d',
'sender': 'YourBrand',
'mobile': '923001234567,923101234567',
'message': 'Flash Sale! 30% off everything today only.',
})
print(response.text)Send Unicode SMS
Set type=unicode to send emoji, Urdu, or any other non-Latin script text. Unicode messages have a shorter per-part character limit than plain text, exactly as with any standard SMS.
Request Example
GET https://sendpk.com/api/sms.php?api_key=3f9a2b7c6e1d4c2a9b0e8d5f1a2b3c4d&sender=YourBrand&mobile=923001234567&message=%D8%A2%D9%BE%DA%A9%D8%A7+%D8%A2%D8%B1%D8%AF%D8%B1+%D9%85%D9%84+%DA%AF%DB%8C%D8%A7&type=unicode
URL-encode the message parameter (as shown above) whenever it contains Unicode characters.
Dynamic / Personalized SMS
Send bulk SMS with unique information for every contact in a file (.txt, .csv, .xls or .xlsx) —
no need to loop single sends. Reference each column in your message with #B#, #C#, #D#
(matching the spreadsheet's column letters), and every recipient gets their own row's values filled in automatically.
Required Parameters
| Parameter | Description |
|---|---|
api_key required | Your API key. |
sender required | Your approved Sender ID / brand name. |
url required | A publicly reachable link to your uploaded .txt/.csv/.xls/.xlsx file. |
message required | Your message with #COLUMN# placeholders, e.g. #B# pulls from column B of the file. |
Optional Parameters
| Parameter | Description |
|---|---|
format optional | Set to json, xml or plain. |
duplicate optional | 0 removes duplicate numbers, 1 keeps them. Defaults to keeping duplicates. |
Request Example
GET https://sendpk.com/api/personalised.php?api_key=3f9a2b7c6e1d4c2a9b0e8d5f1a2b3c4d&sender=YourBrand&url=https://yourdomain.com/contacts.xlsx&message=Your Son #B# Got #C# Marks In #D#, Your Son Result Is #E#. Please contact the school principal for more details.
Sample Output
If column B holds a name, C a score, D a subject and E a result, each recipient gets their own filled-in copy:
Your Son Ali Ahmad Got 1123 Marks In Mathematics, Your Son Result Is Pass. Please contact the school principal for more details.
Your Son Mustafa Kamal Got 330 Marks In Mathematics, Your Son Result Is Fail. Please contact the school principal for more details.
This is the same mail-merge feature behind the "Send Dynamic Message" request in our Postman collection.
Check Balance
Checks your remaining SMS credit through a simple HTTP call — handy for showing a live balance inside your own app or dashboard.
Request Example
GET https://sendpk.com/api/balance.php?api_key=3f9a2b7c6e1d4c2a9b0e8d5f1a2b3c4d
Returns your remaining SMS credit as a plain number, or the matching status code if the request fails.
Delivery Report
Looks up the current delivery status of a previously sent message using the message ID returned by the send API.
Request Example
GET https://sendpk.com/api/delivery.php?api_key=3f9a2b7c6e1d4c2a9b0e8d5f1a2b3c4d&id=29346
Pass the message id from the OK ID: response you received when the message was sent.
Code Examples
A reusable helper function you can paste directly into your project to start sending SMS in one line.
# Reusable shell function
send_sms() {
curl -s -G 'https://sendpk.com/api/sms.php' \
-d "api_key=$SENDPK_API_KEY" \
-d "sender=$SENDPK_SENDER" \
-d "mobile=$1" \
-d "message=$2"
}
send_sms "923001234567" "Hello from cURL!"<?php
function sendSms(string $mobile, string $message): string {
static $apiKey = '3f9a2b7c6e1d4c2a9b0e8d5f1a2b3c4d';
static $sender = 'YourBrand';
static $url = 'https://sendpk.com/api/sms.php';
return file_get_contents($url . '?' . http_build_query([
'api_key' => $apiKey,
'sender' => $sender,
'mobile' => $mobile,
'message' => $message,
]));
}
$result = sendSms('923001234567', 'Hello from PHP!');
echo strpos($result, 'OK') === 0 ? 'Sent! ' . $result : 'Error: ' . $result;async function sendSms(mobile, message) {
const API_KEY = '3f9a2b7c6e1d4c2a9b0e8d5f1a2b3c4d';
const params = new URLSearchParams({
api_key: API_KEY,
sender: 'YourBrand',
mobile,
message,
});
const res = await fetch('https://sendpk.com/api/sms.php?' + params);
return res.text();
}
const result = await sendSms('923001234567', 'Hello from JavaScript!');
console.log(result);import requests
API_KEY = '3f9a2b7c6e1d4c2a9b0e8d5f1a2b3c4d'
SENDER = 'YourBrand'
API_URL = 'https://sendpk.com/api/sms.php'
def send_sms(mobile: str, message: str) -> str:
response = requests.get(API_URL, params={
'api_key': API_KEY,
'sender': SENDER,
'mobile': mobile,
'message': message,
})
return response.text
result = send_sms('923001234567', 'Hello from Python!')
print(result)Best Practices
- Always check that the response starts with
OKbefore assuming a message was accepted. - Save the message ID from each
OK ID:response if you plan to check its delivery report later. - Call the API from your backend, never directly from a browser or mobile app, to keep your
api_keyprivate. - Use
format=jsonif you'd rather parse a structured response than a plain-text line. - For bulk sends, pass a comma-separated
mobilelist; for per-recipient personalization at scale, use the Dynamic SMS endpoint instead of looping single sends.
Postman & Downloads
Prefer exploring the API outside your code editor first? Grab our Postman collection or the full offline documentation bundle.
Postman Collection
Every endpoint pre-built and ready to run — just drop in your own api_key.
Offline Documentation
Download a zip with the full PHP & HTTP code samples for offline reference.
Download Api.zipFrequently Asked Questions
api_key from your dashboard's Profile page. It replaces the older username/password login-pair auth, which is now deprecated for this API.mobile list, e.g. 923001234567,923101234567, and the same message is sent to everyone in the list..csv/.xls/.xlsx file and reference its columns with #B#, #C#, etc. in your message.type=unicode and URL-encode your message parameter.#variable# placeholders. You fill the placeholders by passing a small JSON object as your message parameter alongside your approved template_id — commonly used for OTP and other transactional messages.format=json or format=xml to any request and the same status/ID pair is returned in that structure instead.Support
Need a hand integrating?
Our team can help with integration questions, Sender ID approval, or troubleshooting delivery issues. Reach out any time.