# Pak Sender — Guide & Integration

> Generated from https://paksender.com/docs/guide on 08 Oct 2026, 22:01 (Asia/Karachi)  
> How to use Pak Sender by hand on the website and automatically from your own software.

Give this file to your developer or an AI assistant to integrate Pak Sender quickly. For the full API reference, also download the API docs from the API page.

---

# Guide & Integration



Pak Sender sends SMS, voice calls and emails to **your** customers — OTP codes, invoices, daily payment reports, thank-you messages, loyalty points, offers and new-stock alerts. Everything can be done **by hand on the website** or **automatically from your own software** through the API.


| Feature | Manual (website page) | Automatic (API) |
| --- | --- | --- |
| SMS / voice OTP / voice call | Send Message | POST /messages/send-sms, /messages/send-voice-otp, /messages/send-voice-call |
| One SMS to many numbers | Bulk Campaigns | POST /messages/send-bulk-sms |
| Email campaigns | Email Marketing | — |
| Invoice / receipt / statement | Invoice via Email / SMS | POST /invoices |
| Many people, own amounts | Bulk Invoices | POST /invoices/bulk |
| Daily payments → report | Daily Entries & Reports | POST /entries, /entries/report |
| Repeat daily / weekly / monthly | Invoice form → Schedule / repeat | POST /invoice-schedules |
| Thank-you, points, order updates | Automations (+ Send test) | POST /events |
| Sales, offers, new stock | Offers & Broadcasts | POST /broadcasts |
| Customer list & tags | Customer Contacts | POST /contacts |



## Account setup (once)

 **1 Register & verify your email.** Email marketing works immediately. **2 Submit KYC** (CNIC / business documents). After approval SMS, voice, bulk and API are unlocked. Until then these pages show a lock. **3 Add balance** from Payments. One PKR balance pays for SMS, voice and email. **4 For email:** Email Marketing → **SMTP Settings** → add your mailbox (Gmail app password, Hostinger, Zoho…). Emails are sent from your own address; the API refers to it by its **SMTP username**. **Hitting daily limits?** Add several mailboxes and pass them all — `"smtp": ["a@shop.com","b@shop.com"]` (or select several on the website). Each email goes through the account with the most sends left today, full accounts are skipped and a failed send is retried on the next one. **5 For automation: API Keys** → create a key and paste it into your software. Keep it secret — it can spend your balance. Schedules, recurring invoices, delayed automations and broadcasts run on our servers — nothing has to stay open on your side.

## Who receives what?



We only send to numbers / emails that you give us. This table shows where the recipient comes from in each feature:


| You use… | It goes to… |
| --- | --- |
| Send Message / Bulk Campaign | The number(s) you type or upload |
| Invoice (web or POST /invoices) | The customer_phone (SMS) or customer_email (email) on that invoice |
| Bulk invoices | Each row / document's own phone or email — rows with the same person are merged into one document |
| Daily entries report | The phone / email saved with that customer's entries (customer_ref) |
| Recurring invoice | The customer on the schedule (or the one your source_url returns each time) |
| Automation, audience event_customer | The customer sent with the event |
| Automation / broadcast, audience all | All your Customer Contacts |
| Automation / broadcast, audience tag | Only contacts with that tag (vip, wholesale, lahore…) |

 Contacts who unsubscribe (link in email, or `sms_opt_out` / `email_opt_out`) are skipped automatically by automations and broadcasts. Only message people who expect to hear from you.

## Manual: SMS, voice & email



**Send Message** — choose SMS, Voice OTP or Voice Call, enter the number(s) and text, see the cost preview, press Send. Urdu is supported (Unicode, 70 characters per part). **Bulk Campaigns** — upload a CSV of numbers. **Email Marketing** — contacts, lists, templates and campaigns with open / click tracking.



## Manual: invoices & receipts

 **1**Open **Invoice via Email** or **Invoice via SMS**. **2**Pick the document type — **Invoice**, **Receipt** or **Statement / Report**. **3**Enter the customer, then one line per product / payment (date, description, qty, price). Tax and discount are optional. **4**Choose a template (**Load**) — the live preview shows exactly what the customer receives. **5 Send now**, or **Schedule / repeat** (see recurring). Every invoice is saved in **All Invoices** with print / PDF.

Templates live in **Invoice Templates**. You can also import any Email Marketing template and add placeholders such as `{{customer_name}}`, `{{items_table}}`, `{{total}}`.



## Manual: bulk invoices / reports



**Bulk Invoices** → choose SMS or email and the document type → paste rows:



```
Ali Khan, 03001234567, 2026-09-28, Payment received, 70
Ali Khan, 03001234567, 2026-09-29, Payment received, 80
Sara, 03002222222, 2026-09-29, Voucher #12, 1500
```



Ali gets **one** statement with both dates (total 150), Sara gets her own. The result of every person is shown after sending.



## Manual: daily entries & reports



Use this when a customer has many small payments / vouchers during the day or month.

 **1 Daily Entries & Reports** → add entries (customer ID, name, mobile/email, date, description, amount) — one by one or paste many. **2**The page shows every customer with **new (unreported)** entries and their total. **3**Press **SMS** / **Email** to send that customer's statement now, or **Send all reports now**. **4**Or press **Auto** → every day / week / month / N days, first send time, until date. Each run sends only the new entries; if there are none, nothing is sent or charged.

## Manual: recurring invoices



On the invoice form choose **Schedule / repeat**: one time on a date, every day, week, month or N days; first send date & time (Pakistan time); stop on a date or after N invoices. Manage them in **Recurring Invoices** — send now, pause, resume, cancel.



## Manual: automations, offers & contacts



**Automations** — "when EVENT happens → send". Start from an example (thank-you after order, loyalty points, order shipped, review request after 1 day, sale for everyone, new stock for a tag), adjust the text and press **Send test** to try it on your own number. Events normally come from your software (next section).



**Offers & Broadcasts** — write the offer, choose all contacts or a tag, send now or at a date & time. **Customer Contacts** — add / import customers and tags; contacts are also created automatically from every event.



## Automatic: API basics


 - Base URL: `https://paksender.com/api/v1`
 - Header: `Authorization: Bearer YOUR_API_KEY` (or `X-API-Key`) and `Content-Type: application/json`
 - Every response: `{"status":"success","message":"…","data":{…}}` or `{"status":"error","message":"…","error_code":"…"}`
 - Common error codes: `AUTH_ERROR` (401), `VALIDATION_ERROR` (422), `INSUFFICIENT_BALANCE` (402), `KYC_REQUIRED` / `FEATURE_DISABLED` (403), `NOT_FOUND` (404)
 - Send your own reference (`external_ref`, `external_id`) — it comes back in responses and webhooks, and makes retries safe.



A tiny PHP helper used by the recipes below:



```
<?php
const API_BASE = 'https://paksender.com/api/v1';
const API_KEY = 'YOUR_API_KEY';

function api_call(string $method, string $path, array $body = []): array
{
 $ch = curl_init(API_BASE . $path);
 curl_setopt_array($ch, [
 CURLOPT_CUSTOMREQUEST => $method,
 CURLOPT_RETURNTRANSFER => true,
 CURLOPT_TIMEOUT => 30,
 CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . API_KEY, 'Content-Type: application/json', 'Accept: application/json'],
 CURLOPT_POSTFIELDS => $body ? json_encode($body) : null,
 ]);
 $res = json_decode(curl_exec($ch), true) ?: ['status' => 'error', 'message' => curl_error($ch)];
 curl_close($ch);
 return $res;
}
```



## Recipe: OTP by SMS or voice



```
$code = random_int(100000, 999999); // store it with an expiry on your side
api_call('POST', '/messages/send-sms', [
 'receiver_number' => '+923001234567',
 'message' => "Your login code is $code. Valid for 5 minutes.",
]);
// voice call that reads the code: POST /messages/send-voice-otp {"receiver_number":"+923001234567","message":"482913"}
```



## Recipe: one SMS to many numbers (bulk SMS)



**Website:** Bulk Campaigns → name, text, paste numbers (one per line) or upload a CSV → Send. **API:** up to 10,000 numbers per request — same text, or a personal text per number:



```
// same text for everyone
$r = api_call('POST', '/messages/send-bulk-sms', [
 'campaign_name' => 'Eid greetings',
 'receivers' => ['+923001111111', '03002222222', '+923003333333'], // or "0300…,0301…"
 'message' => 'Eid Mubarak from Your Shop!',
]);
$campaignId = $r['data']['campaign']['id'];

// a different text per number (bills, balances, results…)
api_call('POST', '/messages/send-bulk-sms', ['messages' => [
 ['to' => '+923001111111', 'message' => 'Ali, your bill is Rs 1,200'],
 ['to' => '+923002222222', 'message' => 'Sara, your bill is Rs 950'],
]]);

// progress
api_call('GET', '/messages/bulk/' . $campaignId); // status, sent, failed, errors
```



Campaigns are sent in the background in batches of 50 (usually within a couple of minutes). The balance is checked up front; each SMS is charged when it is sent. Need names, tags and unsubscribe handling? Use Offers & Broadcasts instead.



## Recipe: invoice or receipt when an order is paid



```
api_call('POST', '/invoices', [
 'channel' => 'email', // or 'sms' + customer_phone
 'doc_type' => 'receipt', // invoice | receipt | statement
 'smtp' => 'billing@yourshop.com', // your SMTP username
 'customer_name' => $order->name,
 'customer_email' => $order->email,
 'items' => array_map(fn($i) => ['product' => $i->name, 'qty' => $i->qty, 'price' => $i->price], $order->items),
 'discount' => $order->discount,
 'external_ref' => 'ORDER-' . $order->id,
 'callback_url' => 'https://yourshop.com/webhooks/invoices', // optional
]);
```



Many customers at once (e.g. today's receipts): `POST /invoices/bulk` with `"documents": [ {…}, {…} ]` — up to 100 per call.



## Recipe: monthly billing (fees, rent, internet, membership)



Create the schedule once when the customer subscribes — we send every month until the end date:



```
$r = api_call('POST', '/invoice-schedules', [
 'channel' => 'sms',
 'customer_name' => 'Ali Khan',
 'customer_phone' => '+923001234567',
 'items' => [['product' => 'Monthly fee', 'price' => 3500]],
 'frequency' => 'monthly', // once | daily | weekly | monthly | custom (+ interval_days)
 'start_at' => '2026-10-01 10:00', // Pakistan time
 'end_at' => '2027-06-30 23:59', // or 'max_runs' => 9
 'external_ref' => 'STUDENT-88',
]);
$scheduleId = $r['data']['schedule']['id']; // save it

// later: PATCH /invoice-schedules/{id} {"status":"paused"} | {"status":"active"} | {"status":"cancelled"}
```



Amount changes every month? Add `source_url` — we fetch the current customer / lines from your system right before each send (see Webhooks & live data).



## Recipe: daily report from your POS / ledger



Push every payment, voucher or sale as it happens, then let a schedule send one statement per customer every night:



```
// 1) whenever a payment / voucher is recorded in your software
api_call('POST', '/entries', ['entries' => [[
 'customer_ref' => 'CUST-12', // your customer ID
 'customer_name' => 'Ali Traders',
 'customer_phone' => '+923001234567',
 'date' => date('Y-m-d'),
 'description' => 'Payment received',
 'amount' => 70,
 'external_id' => 'PAY-9001', // same id again = ignored (safe retry)
]]]);

// 2) once per customer: automatic report every day at 9 PM until year end
api_call('POST', '/invoice-schedules', [
 'channel' => 'sms', 'use_entries' => true, 'customer_ref' => 'CUST-12',
 'customer_name' => 'Ali Traders', 'customer_phone' => '+923001234567',
 'frequency' => 'daily', 'start_at' => '2026-09-29 21:00', 'end_at' => '2026-12-31 23:59',
]);

// …or send whenever you want: POST /entries/report {"channel":"sms","customer_ref":"CUST-12"} / {"channel":"sms","all":true}
```



The customer receives, for example: *"Ali Traders: Statement (27 Sep – 29 Sep) · 27 Sep Payment = PKR 70.00 · 28 Sep Payment = PKR 80.00 · Total: PKR 150.00"*. Reported entries are never sent twice.



## Recipe: thank-you + loyalty points



1) Create the automation once (website → Automations, or `POST /automations`) with event `order.completed` and text like *"Thank you {{first_name}}! Order #{{order_id}}. You earned {{points}} points."* 2) From your software, on every order:



```
api_call('POST', '/events', [
 'event' => 'order.completed',
 'customer' => ['external_id' => 'C-12', 'name' => 'Ali Khan', 'phone' => '+923001234567', 'tags' => ['vip']],
 'data' => ['order_id' => '1042', 'amount' => '2,500', 'points' => 25, 'total_points' => 340],
]);
```



Use any event names you like (`points.earned`, `order.shipped`, `birthday`, `payment.due`…) — every active automation with that name runs. Several automations can share one event (e.g. SMS now + review request after 1 day).



## Recipe: sale, offer or new stock



```
api_call('POST', '/broadcasts', [
 'name' => 'New stock — winter jackets',
 'channel' => 'sms', // sms | email | both
 'audience' => 'tag', 'audience_tag' => 'vip', // or 'audience' => 'all'
 'sms_body' => '{{business_name}}: {{product}} now in stock! {{link}}',
 'data' => ['product' => 'Winter jackets', 'link' => 'https://yourshop.com/jackets'],
 'send_at' => '2026-11-01 10:00', // empty = now
]);
```



Keep your contact list in sync with `POST /contacts` (up to 1000 per call, matched by `external_id` / phone / email; tags are merged).



### Broadcast to any list of numbers



No contacts saved? Send straight to a list — on the website choose **Send to → These numbers / emails** and paste one per line, or via API:



```
api_call('POST', '/broadcasts', [
 'name' => 'Eid offer',
 'channel' => 'sms',
 'audience' => 'numbers',
 'recipients' => ['+923001111111', '03002222222', ['phone' => '+923003333333', 'name' => 'Sara', 'data' => ['code' => 'SARA20']]],
 'sms_body' => 'Eid Mubarak {{first_name}}! Use code {{code}} for 20% off.',
 'data' => ['code' => 'EID20'], // default for everyone, per-recipient "data" overrides
 'save_tag' => 'eid-2026', // optional: keep them as contacts with this tag
]);
```



## WooCommerce / WordPress example



Add to your theme's `functions.php` (or a small plugin) together with the helper above:



```
add_action('woocommerce_order_status_completed', function ($order_id) {
 $o = wc_get_order($order_id);
 api_call('POST', '/events', [
 'event' => 'order.completed',
 'customer' => [
 'external_id' => 'WC-' . $o->get_customer_id(),
 'name' => $o->get_formatted_billing_full_name(),
 'phone' => $o->get_billing_phone(),
 'email' => $o->get_billing_email(),
 ],
 'data' => ['order_id' => $o->get_order_number(), 'amount' => $o->get_total(), 'points' => floor($o->get_total() / 100)],
 ]);
});
```



## Webhooks & live data



**Webhook (we → you):** pass `callback_url` on an invoice or schedule; after every send we POST `invoice.sent` / `invoice.failed` with the full invoice and an HMAC signature. Your secret is on the **Recurring Invoices** page.



```
$raw = file_get_contents('php://input');
if (!hash_equals(hash_hmac('sha256', $raw, 'YOUR_WEBHOOK_SECRET'), $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '')) {
 http_response_code(401); exit;
}
$event = json_decode($raw, true); // $event['invoice']['external_ref'], ['status'], ['total'] …
http_response_code(200);
```



**Live data (we ← you):** give a schedule a `source_url`. Right before each send we GET it and use what you return:



```
// https://yourapp.com/sms/invoice-data?schedule_id=…&external_ref=STUDENT-88
echo json_encode([
 'customer_name' => 'Ali Khan',
 'items' => [['product' => 'October fee', 'price' => 3500], ['product' => 'Late fine', 'price' => 200]],
 'due_date' => '2026-10-10',
 'skip' => false, // true = nothing to bill this time (no message, no charge)
]);
```



## How it works inside

 Your software / our website**API check (key, KYC, balance)**Message built from template + your data**Sent now or queued**Balance charged**Logged + webhook
 - **Instant:** single invoices, events with a few recipients and API SMS are sent within the same request.
 - **Queued:** broadcasts, big automations, delayed messages, recurring invoices and daily reports are processed every minute by our scheduler.
 - **Never twice:** each message / schedule run is claimed once; entries are marked when reported; repeated `external_id`s are ignored.
 - **History:** All Invoices, Recurring Invoices, Message History and Message Activity show every message with its status and error.



## Charges & limits


| SMS | Per part — 160 characters (70 for Urdu); long texts use several parts |
| --- | --- |
| Email | Per email, through your own SMTP (your provider's daily limits apply) |
| Invoices, reports, automations, broadcasts | Same as the SMS / email they send — no extra fee |
| Skipped messages | Free (no entries, opted-out contact, no phone / email) |
| Limits per call | Bulk SMS 10,000 numbers · bulk invoices 100 · entries 500 · contacts 1000 · bulk web page 200 recipients |



## Troubleshooting

 KYC_REQUIRED / SMS page lockedYour KYC is not approved yet — email still works. "SMTP not found or not active"Add / activate an SMTP in Email Marketing → SMTP Settings and pass its username as `smtp`. INSUFFICIENT_BALANCETop up; scheduled items retry on their next run. Event returns `automations: 0`No active automation uses that exact event name — check spelling and that it is switched on. Report "nothing sent"That customer has no new entries since the last report (correct behaviour — nothing is charged). CONTENT_BLOCKED / "Message blocked"The text contains prohibited content (gambling / betting promotion, scams, blocked links). Nothing was sent or charged — change the text. A message shows "Skipped"The contact unsubscribed, or has no phone / email for that channel. [Create a free account](https://paksender.com/register) to get your API key and the full API reference.
