PTA-Approved SMS Aggregator · Serving Pakistan since 2014

SMS API

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.

Important

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)
See Verification Options

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.

Onboarding

Getting Started

From signup to your first delivered SMS in a few minutes.

1

Create your free account

Sign up with your name, mobile number and email — no paperwork to get started.

2

Get your Sender ID approved

Verify your account for the route your business needs — Semi Branded, Branded or Short Code (OTP) SMS.

3

Grab your API key

Copy your unique api_key from your dashboard's Profile page — it authenticates every API call you make.

4

Call the API

Hit api/sms.php with your API key, sender ID, recipient and message.

5

Track delivery & balance

Poll delivery.php for a message's status and balance.php for your remaining credit.

Reference

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.

View My API Key

Sending it

Pass api_key as a plain request parameter on every call, via GET query string or POST body:

?api_key=3f9a2b7c6e1d4c2a9b0e8d5f1a2b3c4d&sender=YourBrand&mobile=923001234567&message=Hello

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.

Reference

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.

RouteSender ID
Simple SMSSent from a pre-approved shared name such as SMS Alert — instant approval.
Branded SMSYour own company or brand name — requires a one-time mask approval.
Short Code / OTPDelivered via our dedicated short code route for time-critical codes — default short code is 8584.
Reference

Base URL & Endpoints

There's one endpoint per operation — sending, dynamic/mail-merge sending, checking a delivery report, and checking your balance.

PurposeEndpoint
Send SMS (single, bulk, unicode, fixed/OTP)https://sendpk.com/api/sms.php
Dynamic / personalized SMS from a filehttps://sendpk.com/api/personalised.php
Delivery reporthttps://sendpk.com/api/delivery.php
Check balancehttps://sendpk.com/api/balance.php
GET POST Both are supported. GET is the simplest for quick testing; POST keeps your api_key out of server access logs in production.
Reference

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.

ParameterDescription
api_key requiredYour unique API key, from Profile → API Key.
sender requiredYour approved Sender ID / brand name.
mobile requiredRecipient mobile number, or a comma-separated list for bulk sends, e.g. 923001234567,923101234567.
message requiredThe 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 optionalOne of Jazz, Zong, Ufone, Telenor. Use it to route SMS on ported/MNP numbers, or to force a specific operator.
type optionalSet to unicode to send emoji or non-Latin script text.
template_id optionalYour approved Fixed-SMS/OTP template ID.
format optionalSet 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.

Reference

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

OK ID:29346

The number after ID: is your unique message ID — save it if you plan to check the delivery report later.

Reference

Status Codes

Every response starts with OK on success, or a numeric code that tells you exactly what went wrong.

CodeMeaning
OKMessage was successfully accepted for delivery.
1API key is invalid, expired, or your account is disabled.
2API key is empty.
3Reserved (legacy code, unused with api_key auth).
4Sender ID is empty.
5Recipient is empty.
6Message is empty.
7Invalid recipient number.
8Insufficient credit — top up your balance to continue sending.
9SMS rejected.
API Endpoints

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.

POSTGET
https://sendpk.com/api/sms.php

Creating a template

1

Log in to your dashboard

Open the SMS Templates section from your account.

2

Open Fixed-SMS-Templates

Found in the top-right corner of the SMS Templates page.

3

Submit your content

Write your message with #variable_name# placeholders for anything that changes per recipient.

4

Wait for approval

Once approved you'll get a template_id — ready to use immediately.

Required Parameters

ParameterDescription
template_id requiredYour approved Fixed-SMS/OTP template ID.
message requiredJSON string of variable values, e.g. {"name":"Umair","pin":"456723"}.

Request Example

HTTP
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.

POSTGET
https://sendpk.com/api/sms.php

Request Example

HTTP
GET https://sendpk.com/api/sms.php?api_key=3f9a2b7c6e1d4c2a9b0e8d5f1a2b3c4d&sender=YourBrand&mobile=923001234567&message=Your table is ready, see you soon!

Response Example

OK ID:29346
cURL
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
<?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;
}
JavaScript
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"
Python
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.

POSTGET
https://sendpk.com/api/sms.php

Request Example

HTTP
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

OK ID:29347
cURL
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
<?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;
JavaScript
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());
Python
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.

POSTGET
https://sendpk.com/api/sms.php

Request Example

HTTP
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.

POST
https://sendpk.com/api/personalised.php

Required Parameters

ParameterDescription
api_key requiredYour API key.
sender requiredYour approved Sender ID / brand name.
url requiredA publicly reachable link to your uploaded .txt/.csv/.xls/.xlsx file.
message requiredYour message with #COLUMN# placeholders, e.g. #B# pulls from column B of the file.

Optional Parameters

ParameterDescription
format optionalSet to json, xml or plain.
duplicate optional0 removes duplicate numbers, 1 keeps them. Defaults to keeping duplicates.

Request Example

HTTP
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:

Output
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.

GET
https://sendpk.com/api/balance.php

Request Example

HTTP
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.

GET
https://sendpk.com/api/delivery.php

Request Example

HTTP
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.

Developer Tools

Code Examples

A reusable helper function you can paste directly into your project to start sending SMS in one line.

cURL
# 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
<?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;
JavaScript
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);
Python
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 OK before 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_key private.
  • Use format=json if you'd rather parse a structured response than a plain-text line.
  • For bulk sends, pass a comma-separated mobile list; for per-recipient personalization at scale, use the Dynamic SMS endpoint instead of looping single sends.
Developer Tools

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.

Open Collection

Offline Documentation

Download a zip with the full PHP & HTTP code samples for offline reference.

Download Api.zip
Developer Tools

Frequently Asked Questions

What do I use as my API key?
Copy your unique api_key from your dashboard's Profile page. It replaces the older username/password login-pair auth, which is now deprecated for this API.
Can I send to multiple recipients in one call?
Yes — pass a comma-separated mobile list, e.g. 923001234567,923101234567, and the same message is sent to everyone in the list.
How do I send a unique message per recipient at scale?
Use the Dynamic / Personalized SMS endpoint — upload a .csv/.xls/.xlsx file and reference its columns with #B#, #C#, etc. in your message.
How do I send emoji or Urdu text?
Set type=unicode and URL-encode your message parameter.
What is Fixed-SMS / template_id?
It's a pre-approved message template with #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.
Why did I get status code 8?
Your account has insufficient credit. Top up your balance from your dashboard to continue sending.
How do I check if a message was delivered?
Call delivery.php with the message id you received in the original OK ID: response.
Can I get JSON or XML responses instead of plain text?
Yes — add format=json or format=xml to any request and the same status/ID pair is returned in that structure instead.
Developer Tools

Support

Need a hand integrating?

Our team can help with integration questions, Sender ID approval, or troubleshooting delivery issues. Reach out any time.