W3 SMS API Documentation
Integrate W3 SMS into your application with a few HTTP requests - send single and bulk SMS, check your balance and receive delivery reports.
- Simple IntegrationPlain HTTP, GET or POST
- Secure CredentialsClient ID and Secret
- Delivery ReportsPushed to your server
- Safe RetriesIdempotency keys
1. Getting Started
Welcome to the W3 SMS API Documentation
W3 SMS gives you a simple HTTP API to send SMS from your own software. This guide takes you from your credentials to your first message, then covers bulk sending, balance checks and delivery reports.
2. API Endpoints
Send your requests to these URLs:
https://w3sms.com/send-message
Send SMS - use GET with query parameters, or POST with a form-urlencoded or JSON body. Both behave identically.
https://w3sms.com/check-balance
Check balance.
3. Authentication
Pass your Client ID and Client Secret with every request. You can find them in your W3 SMS account, under Manage API Key.
YOUR_CLIENT_ID
YOUR_CLIENT_SECRET
4. Send SMS
Use the following endpoint to send a single SMS, or several in one call.
Request Parameters
| Parameter | Type | Description |
|---|---|---|
clientIdrequired | string | Your unique client ID. |
clientSecretrequired | string | Your client secret. |
senderIdrequired | string | An approved sender ID assigned to your account. |
numbersrequired | string | Recipient number(s). For bulk SMS, separate numbers with commas. Example: 8801711578523,8801912345678 |
contentsrequired | string | Message body. ASCII up to 160 chars per SMS, Unicode (e.g. Bangla) up to 70 chars per SMS. URL-encode it. |
idempotency_keyoptional | string | Your own reference for this send, e.g. an order number. Repeat a call with the same key and the original answer is returned instead of the message going out twice - the safe way to retry after a timeout. May also be sent as the Idempotency-Key header. Remembered for 24 hours. |
asyncoptional | 0 / 1 | Send 1 to queue the batch instead of waiting for the gateway. The balance is checked and charged straight away, and the call returns 202 with a reference. Recommended for large batches. |
Example
Placeholder credentials are shown - sign in to your account for your own. Replace the number and text and it runs as it stands.
curl -G "https://w3sms.com/send-message" \
--data-urlencode "clientId=YOUR_CLIENT_ID" \
--data-urlencode "clientSecret=YOUR_CLIENT_SECRET" \
--data-urlencode "senderId=YOUR_SENDER_ID" \
--data-urlencode "numbers=8801711578523" \
--data-urlencode "contents=Hello from W3SMS"
curl -X POST "https://w3sms.com/send-message" \
-d "clientId=YOUR_CLIENT_ID" \
-d "clientSecret=YOUR_CLIENT_SECRET" \
-d "senderId=YOUR_SENDER_ID" \
-d "numbers=8801711578523" \
--data-urlencode "contents=Hello from W3SMS"
curl -X POST "https://w3sms.com/send-message" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"clientId": "YOUR_CLIENT_ID",
"clientSecret": "YOUR_CLIENT_SECRET",
"senderId": "YOUR_SENDER_ID",
"numbers": "8801711578523",
"contents": "Hello from W3SMS"
}'
<?php
$payload = [
'clientId' => 'YOUR_CLIENT_ID',
'clientSecret' => 'YOUR_CLIENT_SECRET',
'senderId' => 'YOUR_SENDER_ID',
'numbers' => '8801711578523',
'contents' => 'Hello from W3SMS',
];
$ch = curl_init('https://w3sms.com/send-message');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($payload));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
const res = await fetch('https://w3sms.com/send-message', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET',
senderId: 'YOUR_SENDER_ID',
numbers: '8801711578523',
contents: 'Hello from W3SMS'
})
});
const data = await res.json();
console.log(data);
import requests
payload = {
'clientId': 'YOUR_CLIENT_ID',
'clientSecret': 'YOUR_CLIENT_SECRET',
'senderId': 'YOUR_SENDER_ID',
'numbers': '8801711578523',
'contents': 'Hello from W3SMS',
}
r = requests.post('https://w3sms.com/send-message', data=payload)
print(r.json())
// pubspec.yaml: dependencies: http: ^1.2.0
import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> sendSms() async {
final response = await http.post(
Uri.parse('https://w3sms.com/send-message'),
body: {
'clientId': 'YOUR_CLIENT_ID',
'clientSecret': 'YOUR_CLIENT_SECRET',
'senderId': 'YOUR_SENDER_ID',
'numbers': '8801711578523',
'contents': 'Hello from W3SMS',
},
);
final data = jsonDecode(response.body);
print(data);
}
Success Response
{
"status": 200,
"message": "Message submitted successfully. Delivery status will update via DLR."
}
"Submitted" means the gateway accepted it. Whether each number actually received it arrives later as a delivery report - see Delivery Reports below.
Success Response - queued (async=1)
{
"status": 202,
"reference": "batch_20260911105732_RXfjnh",
"accepted": 250,
"charged": 200.0,
"message": "Batch accepted. Delivery status will update via DLR."
}
422 rather than partly sent - split it into batches.
5. Bulk SMS
Send the same message to many recipients in one call - just provide a comma-separated list of numbers.
Example - Bulk SMS
https://w3sms.com/send-message?clientId=YOUR_CLIENT_ID&clientSecret=YOUR_CLIENT_SECRET&senderId=YOUR_SENDER_ID&numbers=8801XXXXXXXXX%2C8801YYYYYYYYY&contents=Hello+from+W3SMS
Sending a large batch
- Keep each call to 1,000 recipients or fewer; a longer list is refused with
422rather than partly sent. - Add
async=1so the call returns as soon as the batch is charged and queued, instead of waiting for the gateway. A big batch can otherwise outlast your HTTP timeout, leaving you unsure whether it went. - Add an
idempotency_keyso that if the connection drops and you retry, the batch is not sent - and charged - a second time. - The batch is all or nothing: if your balance will not cover every recipient, none are sent.
6. Check Balance
https://w3sms.com/check-balance
Required parameters: clientId, clientSecret.
Example
https://w3sms.com/check-balance?clientId=YOUR_CLIENT_ID&clientSecret=YOUR_CLIENT_SECRET
Success Response
{
"status": 200,
"balance": 500.00
}
7. Delivery Reports (DLR Push)
Instead of polling for status, we push a real-time webhook to your server whenever an SMS is delivered or fails. Set your Success and Fail URLs under DLR Push Config in your account.
How it works
- SMS delivered - we send a request to your Success URL
- SMS failed - we send a request to your Fail URL
- Method (GET / POST) is configurable in the DLR settings.
Webhook Payload
| Field | Description |
|---|---|
message_id | Unique message id returned when the SMS was sent. |
number | Recipient phone number. |
status | delivered or failed |
raw_status | Raw status string from the upstream gateway. |
sent_at | When the SMS was submitted (ISO 8601). |
reported_at | When the delivery report was received (ISO 8601). |
Example payload (POST JSON)
{
"message_id": "296334",
"number": "8801XXXXXXXXX",
"status": "delivered",
"raw_status": "success",
"sent_at": "2026-05-31T18:05:45+06:00",
"reported_at": "2026-05-31T18:12:10+06:00"
}
8. Status Codes
| HTTP / Status | Meaning | When it happens |
|---|---|---|
| 200 | Accepted | The gateway took the message and your balance was charged. Delivery itself is reported later by DLR. |
| 202 | Queued | Only with async=1. Charged and queued; the response carries a reference. |
| 404 | User not found | Invalid clientId or clientSecret. |
| 404 | Sender ID not found | The senderId is not assigned to your account. |
| 406 | Insufficient balance | Your account balance is less than the calculated charge. |
| 406 | Gateway unavailable | No active SMS gateway is configured. Contact support. |
| 406 | Invalid phone number | The gateway rejected the destination number. |
| 406 | Sender does not match your package | A masking package cannot send through a non-masking sender ID, or the other way round. The message names which. |
| 409 | Duplicate in flight | An earlier call with the same idempotency_key is still running. Wait for it rather than retrying. |
| 422 | Validation error | A required parameter is missing or malformed, or the list held more than 1,000 recipients. |
| 502 | Gateway refused | Every gateway turned the batch down. Nothing was sent and the charge was returned to your balance. |
| 503 | No gateway available | No SMS gateway is active. Contact support. |
406. If a gateway then refuses the batch the charge is put straight back; if a delivery report later says a message never arrived, that message is refunded; and if no delivery report arrives within 48 hours, it is settled as undelivered and refunded then. Every movement appears in your transaction history.
9. WordPress Plugin
Sending from a WordPress site? Skip the code above - install the official plugin instead: a Settings screen for the same credentials, a one-function API (w3sms_send_sms()), and optional automatic SMS on WooCommerce order updates and Contact Form 7 submissions.
Installation
- wp-admin - Plugins - Add New - Upload Plugin, choose the downloaded zip, then Install and Activate.
- Open Settings - W3 SMS and enter your Client ID, Client Secret and Default Sender ID.
- Use the Send Test SMS tool on the same screen to confirm it works.
Function reference
| Function | Returns | Notes |
|---|---|---|
w3sms_send_sms( $numbers, $message, $sender = null ) | true | WP_Error | $numbers accepts one MSISDN or several comma-separated. $sender overrides the saved default. |
w3sms_check_balance() | float | WP_Error | The account balance, in the currency the API reports it in. |
10. WHMCS Module
Running a hosting or billing business on WHMCS? This addon texts your clients automatically - new invoice, payment received, a staff reply on their ticket, or a service suspension - each one an independent on/off switch in the module's settings.
Installation
- Extract the zip so the path is modules/addons/w3sms/w3sms.php on your WHMCS install.
- Admin area - Setup - Addon Modules - find W3 SMS - Activate.
- Click Configure: enter your Client ID, Client Secret and Default Sender ID, tick the events you want, and grant your admin role access.
- Open Addons - W3 SMS and use the Send Test SMS tool to confirm it works.
Notification events
| Setting | WHMCS hook | Client is texted when... |
|---|---|---|
| SMS on new invoice | InvoiceCreated | an invoice is generated for them (recurring or one-off). |
| SMS on payment received | InvoicePaid | one of their invoices is marked Paid. |
| SMS on staff ticket reply | TicketAdminReply | a staff member replies to their open support ticket. |
| SMS on service suspension | AfterModuleSuspend | one of their hosting services is suspended. |