Bulk SMS API for Developers
Integrate reliable SMS messaging into your application using BulkSMSOnline HTTP API, REST API, SMPP connectivity, MNP lookup, number validation, delivery reports, and webhook callbacks.
HTTP SMS API
https://api.bulksmsonline.co/smsapi
YOUR_USERNAME
YOUR_PASSWORD
t
1234567890
YourBrand
Hello from BulkSMSOnline
Getting Started
Select an API category from the left menu to view only the related documentation.
SMS Integration Options Built for Developers
BulkSMSOnline gives developers several ways to connect applications, CRMs, SaaS platforms, billing systems, notification engines, and enterprise messaging workflows to global SMS delivery.
Simple URL-based SMS sending for fast integration and legacy systems.
JSON-based API for modern applications, backend services, and scalable workflows.
Low-latency SMPP connectivity for high-volume and carrier-grade integrations.
Send Your First SMS in Minutes
Use this quick integration flow when you want to test SMS delivery before building a full production setup.
Create or log in to your account
Use your BulkSMSOnline account username and password for API authentication.
Choose your API type
Use HTTP API for quick URL-based sending, REST API for JSON workflows, or SMPP for high-throughput connectivity.
Send a test request
Start with a test recipient number and a verified sender format before moving to production traffic.
Track delivery
Use delivery reports, message IDs, and webhook callbacks to reconcile message status in your system.
Authentication & Credentials
BulkSMSOnline APIs use account credentials and service tokens depending on the API type. Keep credentials secure and never expose them in frontend JavaScript, public repositories, or mobile app bundles.
Uses username and password parameters in the API request.
Generate a token first, then include the token with each SMS request.
Uses SMPP username, password, host, port, bind type, and IP whitelist approval.
Use your configured callback URL to receive delivery status updates from BulkSMSOnline.
HTTP SMS API
The HTTP API is the fastest way to send SMS messages using a simple GET or POST request. It is useful for legacy systems, direct server-side integrations, and lightweight notification workflows.
Endpoint
https://api.bulksmsonline.co/smsapi?username=XXXX&password=YYYYY&type=t&to=0000000000&source=sender&message=YourText
Parameters
| Presence | Parameter | Description |
|---|---|---|
| Mandatory | username |
Your account username. |
| Mandatory | password |
Your account password.
Note:
If the password contains special characters, spaces, symbols, or reserved URL characters, it must be URL-encoded before being sent via the API.
|
| Mandatory | type |
Defines the SMS message type.
|
| Mandatory | to |
One or more recipient phone numbers, separated by commas. Maximum 30 numbers per request. |
| Mandatory | source |
The sender ID/name that will appear as the SMS sender.
|
| Mandatory | message |
The SMS message body.
|
| Optional | scheduled |
Schedule the SMS to be sent at a future date and time.
Example:
scheduled=2020-01-13T12:49:00
|
HTTP API Response Codes
The HTTP SMS API returns a response code after each request. A successful request returns
OK|<MESSAGE_ID>. Error responses return an error code that explains why the
SMS request was rejected or could not be processed.
| Response / Error Code | Meaning | Description | Recommended Action |
|---|---|---|---|
OK|<MESSAGE_ID> |
Message accepted | The SMS request was submitted successfully. The API response includes a unique message ID. | Save the returned message ID for delivery tracking, logs, and support reference. |
E0002 |
Invalid request | The request URL is invalid, or one or more required parameters are missing, empty, or sent in the wrong format. | Check the request URL and make sure all required parameters are included correctly. |
E0003 |
Invalid username or password | The username or password parameter is missing, incorrect, or not formatted properly. | Verify the API credentials. If the password contains special characters, URL-encode it before sending the request. |
E0004 |
Invalid message type |
The type parameter is invalid. Supported values include
t for plain text SMS and u for Unicode SMS.
|
Send a valid message type according to the message encoding you are using. |
E0005 |
Invalid message body | The SMS message text is empty, invalid, or not encoded correctly. | Make sure the message body is not empty. Plain text messages should be URL-encoded. Unicode messages should be encoded in UTF-16BE. |
E0006 |
Invalid recipient number |
The to parameter contains an invalid mobile number or unsupported
number format.
|
Use international MSISDN format without spaces or invalid characters. For multiple recipients, separate numbers with commas. |
E0007 |
Invalid sender ID |
The source parameter does not match the allowed sender ID format.
Numeric sender IDs can contain up to 18 digits, while alphanumeric sender IDs can
contain up to 11 characters.
|
Check the sender ID format and confirm that the sender is allowed for the destination country, route, or SMSC. |
E0008 |
Authentication failed | The API credentials are incorrect, inactive, or not allowed to use the requested API service. | Verify the account username, password, account status, and API access permissions. |
E0010 |
Internal server error | The request could not be processed because of a temporary system-side issue. | Retry after a short time. If the issue continues, contact support with the request URL, timestamp, and account username. |
E0022 |
Insufficient balance | The account does not have enough SMS credit to submit the message. | Top up the account balance and retry the request. |
E0033 / HTTP 429 |
Rate limit exceeded | The API sending rate limit has been exceeded. The maximum allowed rate is 30 SMS submissions per second. | Reduce the sending speed, queue messages on your side, and retry after a short delay. |
E0044 |
Mobile network not supported | The destination number belongs to a mobile network that is not currently supported by the selected route or service. | Check the destination network and contact support if you need coverage for this operator or country. |
HTTP Examples
Use type=t for English or Latin-based SMS messages. The message value must be URL-encoded before sending.
https://api.bulksmsonline.co/smsapi?username=XXXX&password=YYYYY&type=t&to=00000000&source=YourBrand&message=Hello%20customer%2C%20your%20code%20is%201234
Use type=u for Unicode messages such as Arabic, Chinese, or other non-Latin languages. The message text must be encoded in UTF-16BE before sending.
https://api.bulksmsonline.co/smsapi?username=XXXX&password=YYYYY&type=u&to=00000000&source=YourBrand&message=06450631062D06280627
Account Balance API
Use the Account Balance API to check the available SMS balance for your account. The endpoint supports both GET and POST, but POST is recommended for better credential privacy.
https://api.bulksmsonline.co/balance?username=XXXX&password=YYYYY
curl -X POST https://api.bulksmsonline.co/balance \
-d "username=XXXX" \
-d "password=YYYYY"
| Parameter | Required | Method | Description |
|---|---|---|---|
username |
Yes | GET / POST | Your BulkSMSOnline account username. |
password |
Yes | GET / POST | Your BulkSMSOnline account password. |
Response Format
The API returns a plain text response. A successful request returns the current account balance. Failed requests return a two-digit response code.
125.000
| Response | Status | Description |
|---|---|---|
125.000 |
Success | The account was authenticated and the current SMS balance was returned. |
00 |
Missing Parameters | The request must include both username and password. |
01 |
Username Error | The username parameter is empty. |
02 |
Password Error | The password parameter is empty. |
03 |
Username Error | The username length is invalid. Username must be less than 30 characters. |
04 |
Password Error | The password length is invalid. Password must be less than 20 characters. |
05 |
Username Error | The username contains invalid characters. |
06 |
Password Error | The password contains invalid characters. |
07 |
Authentication Failed | The username/password is incorrect, the account is not active, or the account is not allowed to use this API. |
08 |
Invalid Request | The same parameter was sent more than once or sent in both GET and POST. |
99 |
System Error | Temporary system error. The request could not be processed due to an internal server or database issue. |
REST SMS API
Use the REST SMS API to send SMS messages from your application over HTTPS using JSON requests and structured JSON responses. The API supports single SMS sending, bulk sending to multiple recipients, and scheduled SMS delivery using a generated REST API token.
Base URL
Send REST API requests over HTTPS using the versioned base URL below.
The current REST SMS API version is v1, and production integrations
should use this versioned URL for better compatibility.
https://api.bulksmsonline.co/rest/api/v1
Generate REST API Token
Generate a temporary REST API token using your BulkSMSOnline username and password.
Use this token when calling the REST API by passing it in the token
HTTP header.
GET https://api.bulksmsonline.co/rest/api/v1/sms/gettoken/username/{YourUsername}/password/{YourPassword}
| Parameter | Location | Required | Description |
|---|---|---|---|
username |
Path | Yes | Your account username or registered mobile number. |
password |
Path | Yes | Your account password. |
Successful Token Response
{
"token": "YOUR_GENERATED_REST_TOKEN"
}
Send SMS
Use this endpoint to send one SMS or a bulk SMS request through the REST API.
The request body must be sent as JSON, and the generated REST API token must
be passed using the token HTTP header. Each request supports up to
30 destination numbers in the to array.
POST https://api.bulksmsonline.co/rest/api/v1/sms/send/
Required Headers
token: YOUR_GENERATED_REST_TOKEN
Content-Type: application/json
Accept: application/json
Request Body
Send SMS requests as a JSON object using Content-Type: application/json.
The to field is an array, so you can send to one recipient or multiple
recipients in the same request. For bulk sending, include up to
30 destination numbers per request.
Destination numbers must be provided in international MSISDN format, such as
1234567890 or +1234567890. Do not use the international
dialing prefix 00. For best results, send numbers as digits only,
without spaces, brackets, or dashes.
{
"from": "YourBrand",
"to": [
"1234567890"
],
"type": "Text",
"content": "Your SMS message",
"sendDateTime": null
}
SMS Request Object Parameters
| Field | Type | Required | Nullable | Description |
|---|---|---|---|---|
from |
string | No | Yes |
Sender ID or originator name. If omitted or set to null, the system
may use the default originator available for the account or route.
|
to |
array of strings | Yes | Yes |
Destination mobile numbers in international MSISDN format, such as
1234567890 or +1234567890. For bulk sending,
include multiple destination numbers in the to array. A single
REST SMS request can include up to 30 destination numbers.
|
type |
string enum | Yes | No |
SMS message type. Supported values:
Text, UniCode.
|
content |
string | Yes | Yes | The SMS message body to be delivered to the recipient. |
sendDateTime |
string/date-time | No | Yes |
Schedule the SMS to be sent at a future date and time. The value must be
provided in ISO 8601 format: yyyy-MM-ddTHH:mm:ss. The scheduled
time must be based on the UTC-04:00 timezone. Use
null or omit the field for immediate sending.
Example: "sendDateTime": "2020-01-13T12:49:00"
|
Example Send SMS Request
curl -X POST "https://api.bulksmsonline.co/rest/api/v1/sms/send/" \
-H "token: YOUR_GENERATED_REST_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"from": "YourBrand",
"to": [
"1234567890",
"1234567891",
"1234567892"
],
"type": "Text",
"content": "Your SMS message",
"sendDateTime": null
}'
REST API Formats and Rules
| Item | Rule |
|---|---|
| Protocol | HTTPS is supported and recommended for all REST API requests. |
| Request format | Requests must be sent as valid JSON using application/json. |
| Response format | Responses are returned as JSON unless otherwise specified. |
| Invalid JSON | Requests with invalid JSON may be rejected with a bad request response. |
| Null values | Nullable fields may be omitted or sent as null where supported. |
| MSISDN format |
Mobile numbers should be sent in international format, with or without a leading
+, and without a leading 00.
|
| Number normalization |
Spaces, dashes, and brackets in destination numbers are ignored by the API.
Returned MSISDNs are normalized without + or 00.
|
Rate Limits
The REST SMS API supports sending up to 30 SMS messages per second. This limit is calculated by the number of destination messages, not only by the number of API requests.
to array, it counts as 30 SMS messages and uses the full 30 SMS/second
allowance for that second.
| Limit Type | Limit | Details |
|---|---|---|
| REST API send rate | 30 SMS / second | The API can process up to 30 destination SMS messages per second. If you send to multiple recipients in one request, each recipient counts as one SMS message. |
| Recipients per request | Maximum 30 numbers |
The to array can include up to 30 destination mobile numbers
in a single REST SMS request.
|
| Large campaigns | Split into batches | For campaigns larger than 30 recipients, split the campaign into multiple REST requests while keeping the sending speed within 30 SMS per second. |
Generate Token HTTP Status Codes
The token endpoint may return the following HTTP status codes.
| HTTP Status | Meaning | Description |
|---|---|---|
200 OK |
Success | Returns the newly generated REST API token. |
401 Unauthorized |
Unauthorized | The provided username or password is incorrect. |
402 Payment Required |
Payment Required | The account has zero balance or the account/service has expired. |
402 Payment Required |
Forbidden / Invalid Action | The request contains an invalid action or the account is not allowed to perform the action. |
404 Not Found |
Invalid Path | The requested endpoint path is invalid. |
405 Method Not Allowed |
Wrong Method | The endpoint was called using an unsupported HTTP method. |
500 Internal Server Error |
Server Error | An unexpected server-side error occurred. |
503 Service Unavailable |
Service Unavailable | The service is temporarily unavailable. |
Send SMS Response Codes
The send SMS endpoint may return a response containing a code value. The following
response codes are used to indicate whether the SMS request was accepted or rejected.
| HTTP Status | Code | Description | Recommended Developer Action |
|---|---|---|---|
200 |
Success |
SMS request was accepted successfully. | No action required. Store the API response for tracking and audit purposes. |
400 |
Bad Request |
Invalid parameters were provided in the request. | Check the JSON body, required fields, destination numbers, sender ID, and message type. |
401 |
Unauthorized |
The REST token is missing, invalid, or expired. | Generate a new token and send it using the token HTTP header. |
404 |
Not Found |
The endpoint path is invalid. | Confirm that you are using the correct versioned endpoint URL. |
405 |
- |
The HTTP method is not allowed. | Use POST for sending SMS. |
500 |
- |
Internal server error. | Retry later. If the issue continues, contact support with the request details. |
503 |
- |
Service unavailable. | Retry after a short delay. |
Interactive Swagger API Documentation
Use the Swagger documentation to inspect REST API endpoints, request formats, response objects, and available operations directly from the API specification.
SMPP API for High-Volume SMS
The SMPP API is designed for customers who need direct protocol-level SMS connectivity, low latency, higher throughput, delivery report handling, and more control over message submission. SMPP is commonly used by telecom providers, aggregators, platforms, and high-volume senders that need a persistent SMS connection instead of request-based HTTP APIs.
SMPP Connection Details
| Setting | Value | Notes |
|---|---|---|
| Host | smpp.bulksmsonline.com |
Production SMPP host. |
| Port | 8889 |
SMPP connection port. |
| Username / System ID | Provided by support | Your SMPP account username, also commonly used as the SMPP system ID. |
| Password | Provided by support | Your SMPP account password. |
| Bind modes | Transmitter / Receiver / Transceiver | Use transmitter mode for sending, receiver mode for delivery reports, or transceiver mode for both sending and receiving on the same connection. |
| Maximum binds | 2 binds by default | Each SMPP account includes 2 default binds. Contact your account manager if you need more concurrent connections. |
| IP whitelist | Required | Your sending server IP address must be added to the firewall whitelist before you can connect to the SMPP server. |
| SMSC timezone | UTC |
BulkSMSOnline SMSC uses UTC for SMPP processing and timing. |
Supported SMPP PDUs
The SMPP interface supports the standard PDU operations required for binding, message submission, delivery report receiving, link checking, message query, replacement, cancellation, and graceful session closure.
| PDU | Direction | Purpose |
|---|---|---|
bind_transmitter / bind_transmitter_resp |
Client ↔ SMSC | Bind as a transmitter to submit outbound SMS messages. |
bind_receiver / bind_receiver_resp |
Client ↔ SMSC | Bind as a receiver to receive delivery reports or inbound SMPP messages. |
bind_transceiver / bind_transceiver_resp |
Client ↔ SMSC | Bind as a transceiver to send messages and receive reports on the same connection. |
submit_sm / submit_sm_resp |
Client ↔ SMSC | Submit an outbound SMS message and receive the submission response. |
data_sm / data_sm_resp |
Client ↔ SMSC | Submit or receive message data using the SMPP data_sm operation. |
deliver_sm / deliver_sm_resp |
SMSC ↔ Client | Receive delivery reports or mobile-originated messages, depending on route support. |
enquire_link / enquire_link_resp |
Client ↔ SMSC | Keep the SMPP session alive and verify that the connection is still active. |
unbind / unbind_resp |
Client ↔ SMSC | Close the SMPP session gracefully. |
generic_nack |
Client ↔ SMSC | Generic negative acknowledgement for invalid or unsupported PDU handling. |
query_sm / query_sm_resp |
Client ↔ SMSC | Query the status of a previously submitted message where supported. |
cancel_sm / cancel_sm_resp |
Client ↔ SMSC | Request cancellation of a scheduled or pending message where supported. |
replace_sm / replace_sm_resp |
Client ↔ SMSC | Request replacement of a previously submitted message where supported. |
Throughput, Window Size & Keepalive
The default SMPP throughput is 10 MT messages per second per bind. Higher throughput may be available by request and depends on account approval, route capacity, and operator limits.
SMPP can support high-volume sending up to 60 messages per second where enabled for the account and supported by the destination route.
Recommended default window size is 5 open requests. This means up to 5 submit requests may be waiting for responses at the same time.
Send enquire_link every 60 seconds to keep the SMPP
connection alive and detect broken sessions.
0x00000058.
Sender ID, TON/NPI & MSISDN Format
SMPP source and destination addressing should be configured correctly using the appropriate TON and NPI values for the sender and recipient format used by your SMPP client.
| Item | Limit / Format | Notes |
|---|---|---|
| Alphanumeric sender ID | Maximum 11 characters | Use for brand names or approved alphanumeric originators where supported by the route and destination country. |
| Numeric sender / MSISDN sender | Maximum 18 digits | Numeric sender IDs should follow MSISDN-style numbering rules. |
| Destination MSISDN | CC + NDC + SN |
Use international number format: country code, national destination code, and subscriber number. |
| Country Code | CC |
The international country code, such as 1, 44, or 62. |
| National Destination Code | NDC |
The network or area portion of the mobile number. |
| Subscriber Number | SN |
The final subscriber number portion of the MSISDN. |
Submitting Messages
Messages can be submitted using submit_sm or data_sm. Message content
may be sent using either the short_message field or the message_payload
optional parameter, depending on your SMPP client implementation and message type.
| Submission Item | Supported Value | Details |
|---|---|---|
| Submission PDU | submit_sm or data_sm |
Used to submit outbound SMS messages through the SMPP bind. |
| Message content field | short_message or message_payload |
Use the field supported by your SMPP client and message encoding requirements. |
| Standard GSM message size | Up to 140 bytes | Message size depends on network and encoding. For GSM SMS, the message byte limit is commonly 140 bytes. |
| Concatenated SMS | Supported using UDH | Long SMS messages may be sent using User Data Header segmentation. UDH bytes are included in the total message size limit. |
Submit Responses
A successful submit response returns command status 0x00000000 and a non-empty
message reference. A failed submit response returns an SMPP command status error code or
vendor-specific error code.
| Response Type | Command Status | Meaning | Developer Action |
|---|---|---|---|
| Positive submit response | 0x00000000 |
No error. Message was accepted by the SMSC. | Store the returned message reference for delivery report matching. |
| Negative submit response | Non-zero error code | The message was rejected or could not be processed. | Check the error code, request fields, sender ID, destination number, and throughput. |
Delivery Reports
Delivery reports are returned through deliver_sm. To receive delivery reports,
connect using receiver or transceiver mode, depending on your SMPP client design.
| DLR Status | Description | Meaning |
|---|---|---|
DELIVRD |
Message delivered to handset. | The SMS was successfully delivered to the recipient device. |
FAILED |
Message could not be delivered. | The message failed before successful delivery. |
EXPIRED |
Message validity period expired. | The SMS expired before it could be delivered. |
UNDELIV |
Message is undeliverable. | The destination could not receive the message. |
REJECTD |
Message rejected. | The message was rejected by the route, SMSC, operator, or filtering layer. |
SMPP Error Codes
The following SMPP command status values may be returned in SMPP responses. A status value of
0x00000000 means no error. Non-zero values indicate that the SMPP request was
rejected or could not be processed.
| Hex Value | Decimal | Description |
|---|---|---|
0x00000000 | 0 | No Error |
0x00000001 | 1 | Message length is invalid |
0x00000002 | 2 | Command length is invalid |
0x00000003 | 3 | Invalid Command ID |
0x00000004 | 4 | Incorrect BIND Status for given command |
0x00000005 | 5 | ESME already in bound state |
0x00000006 | 6 | Invalid Priority Flag |
0x00000007 | 7 | Invalid Registered Delivery Flag |
0x00000008 | 8 | System Error |
0x00000009 | - | Reserved |
0x0000000A | 10 | Invalid Source Address |
0x0000000B | 11 | Invalid Destination Address |
0x0000000C | 12 | Message ID is invalid |
0x0000000D | 13 | Bind Failed |
0x0000000E | 14 | Invalid Password |
0x0000000F | 15 | Invalid System ID |
0x00000010 | 16 | Reserved |
0x00000011 | 17 | Cancel SM Failed |
0x00000012 | - | Reserved |
0x00000013 | 19 | Replace SM Failed |
0x00000014 | 20 | Message Queue Full |
0x00000015 | 21 | Invalid Service Type |
0x00000016 | - | Reserved through 0x00000032 |
0x00000033 | 51 | Invalid number of destinations |
0x00000034 | 52 | Invalid Distribution List name |
0x00000035 | 53 | Reserved through 0x0000003F |
0x00000040 | 64 | Destination flag is invalid for submit_multi |
0x00000041 | - | Reserved |
0x00000042 | 66 | Invalid submit with replace request; submit_sm with replace_if_present_flag set |
0x00000043 | 67 | Invalid esm_class field data |
0x00000044 | 68 | Cannot submit to distribution list |
0x00000045 | 69 | submit_sm or submit_multi failed |
0x00000046 | - | Reserved through 0x00000047 |
0x00000048 | 72 | Invalid Source Address TON |
0x00000049 | 73 | Invalid Source Address NPI |
0x00000050 | 80 | Invalid Destination Address TON |
0x00000051 | 81 | Invalid Destination Address NPI |
0x00000052 | - | Reserved |
0x00000053 | 83 | Invalid system_type field |
0x00000054 | 84 | Invalid replace_if_present flag |
0x00000055 | 85 | Invalid number of messages |
0x00000056 | - | Reserved through 0x00000057 |
0x00000058 | 88 | Throttling error; ESME has exceeded allowed message limits |
0x00000059 | 89 | Reserved through 0x00000060 |
0x00000061 | 97 | Invalid Scheduled Delivery Time |
0x00000062 | 98 | Invalid message validity period / expiry time |
0x00000063 | 99 | Predefined Message Invalid or Not Found |
0x00000064 | 100 | ESME Receiver Temporary Application Error Code |
0x00000065 | 101 | ESME Receiver Permanent Application Error Code |
0x00000066 | 102 | ESME Receiver Reject Message Error Code |
0x00000067 | 103 | query_sm request failed |
0x00000068 | 104 | Reserved through 0x000000BF |
0x000000C0 | 192 | Error in the optional part of the PDU body |
0x000000C1 | 193 | Optional parameter not allowed |
0x000000C2 | 194 | Invalid parameter length |
0x000000C3 | 195 | Expected optional parameter missing |
0x000000C4 | 196 | Invalid optional parameter value |
0x000000C5 - 0x000000FD | - | Reserved |
0x000000FE | 245 | Delivery Failure, used for data_sm_resp |
0x000000FF | 255 | Unknown Error |
0x00000100 - 0x000003FF | - | Reserved for SMPP extension |
SMS Delivery Reports
Delivery reports help you track the lifecycle of each submitted SMS message, including whether it was delivered, failed, expired, rejected, or remains undeliverable.
Common Delivery Statuses
Delivery report statuses show the final or latest delivery result returned for an SMS message.
Use the smsid value from the webhook callback to match each status update with
the original SMS submission in your system.
| Status | Meaning | Description | Recommended Action |
|---|---|---|---|
DELIVRD |
Delivered | The message was successfully delivered to the recipient handset. | Mark the SMS as delivered in your system. |
FAILED |
Failed | The message could not be delivered. This may happen because of route, operator, handset, or destination-related issues. | Mark the SMS as failed and review the destination number, route, sender ID, or message content if needed. |
EXPIRED |
Expired | The message validity period expired before the SMS could be delivered. | Mark the SMS as expired. You may retry later if the message is still relevant. |
UNDELIV |
Undeliverable | The message was reported as undeliverable by the SMSC, route, or mobile network. | Mark the SMS as undeliverable and check whether the mobile number is valid and reachable. |
REJECTD |
Rejected | The message was rejected by the route, operator, SMSC, filtering layer, or destination rules. | Mark the SMS as rejected and review the sender ID, message content, route permissions, and destination requirements. |
smsid
instead of creating duplicate delivery records.
Delivery Report Webhook Callback
Delivery Report Webhook callbacks allow your system to receive automatic SMS status updates when delivery information becomes available. Instead of manually checking message status, BulkSMSOnline can send the delivery result directly to your webhook URL.
Webhook Endpoint Requirements
Your webhook URL must be publicly reachable from our backend and should be able to accept
POST, GET, and HEAD requests. Delivery report data is
sent by POST. Our backend may also send GET or HEAD
requests for connectivity checks, validation, or retry handling. You can safely ignore
GET and HEAD requests, but your endpoint should still return a
successful HTTP response.
Your webhook endpoint must be accessible from the public internet. HTTPS is recommended for production integrations.
Your endpoint should accept POST, GET, and HEAD.
Process the delivery report only when the request method is POST.
Return HTTP 200 OK after receiving the callback. Any server error,
timeout, blocked request, or non-200 response may be treated as a failed callback.
Return the response quickly. Do not make the webhook wait for slow database actions, external APIs, or heavy processing.
Webhook Payload Format
Delivery report callbacks are sent as form-style key/value data. Your endpoint should read the incoming request body and parse the delivery report fields.
source=YourBrand&msisdn=12345678999&status=DELIVRD&sentdate=5%2f14%2f2026+10%3a30%3a29+AM&smsid=8ff01703-5ff0-4f9e-8db7-d3263d75db07
Webhook Parameters
| Parameter | Example | Description |
|---|---|---|
source |
YourBrand |
The sender ID or source value used when the SMS was submitted. |
msisdn |
12345678999 |
The destination mobile number that received the SMS delivery status update. |
status |
DELIVRD |
The delivery status returned for the SMS, such as delivered, failed, expired, undeliverable, or rejected. |
sentdate |
5/14/2026 10:30:29 AM |
The date and time associated with the SMS status update. The value may be URL-encoded in the webhook body. |
smsid |
8ff01703-5ff0-4f9e-8db7-d3263d75db07 |
The unique SMS message ID. Use this value to match the delivery report with the original SMS submission in your system. |
Delivery Status Values
| Status | Meaning | Recommended Action |
|---|---|---|
DELIVRD |
The message was delivered to the recipient handset. | Mark the message as delivered in your system. |
FAILED |
The message could not be delivered. | Mark the message as failed and review the destination or route if needed. |
EXPIRED |
The message validity period expired before successful delivery. | Mark the message as expired. |
UNDELIV |
The message was undeliverable. | Mark the message as undeliverable and check the recipient number if needed. |
REJECTD |
The message was rejected by the route, operator, or filtering layer. | Mark the message as rejected and review the sender, content, or destination rules. |
Retries & Expected Response
Your webhook endpoint should return HTTP 200 OK when the callback is received
successfully. If your server does not respond, returns an error, blocks the request, or returns
a non-200 status, our backend will retry the callback every 30 seconds until
a successful server-side response is received.
HTTP/1.1 200 OK
smsid and
status more than once without creating duplicate records or incorrect message states.
Webhook Speed & Performance
Webhook delivery speed depends partly on your server performance, database speed, network availability, and how quickly your endpoint returns a response. If your webhook performs slow database writes, calls external services, or waits for long processing before responding, delivery report processing may become slower.
| Best Practice | Why It Matters |
|---|---|
Return HTTP 200 quickly |
A fast response confirms that your server received the callback and helps avoid unnecessary retries. |
| Process callbacks asynchronously | Save the callback quickly or push it into a queue, then process heavier database updates in the background. |
Index the smsid field |
Using an indexed message ID makes delivery report matching faster and reduces database lookup time. |
| Avoid slow external API calls |
Do not make the webhook response wait for third-party services. Process those
actions after returning HTTP 200.
|
| Log the raw callback body | Keeping the raw callback helps with reconciliation, debugging, and support investigations. |
Webhook Security
Your webhook URL should be difficult to guess and should be protected on your side. For example, you can include a private reference value in the URL path or query string and reject requests that do not include it.
POST, GET, and HEAD, and return HTTP 200
only after your application has safely received the callback.
MNP Lookup API
Use the MNP Lookup API to check mobile number portability, roaming status, network-level details, and HLR lookup information that can help improve routing decisions, database quality, and delivery cost control.
Endpoint
The endpoint supports both GET and POST. POST is recommended because it keeps your credentials out of the URL, browser history, and most server/proxy logs.
https://api.bulksmsonline.co/mnp?username=XXXX&password=YYYYY&msisdn=12025550100
curl -X POST https://api.bulksmsonline.co/mnp \
-d "username=XXXX" \
-d "password=YYYYY" \
-d "msisdn=12025550100"
MNP Request Parameters
| Presence | Parameter | Method | Description |
|---|---|---|---|
| Mandatory | username |
GET / POST | Your BulkSMSOnline account username. |
| Mandatory | password |
GET / POST | Your BulkSMSOnline account password. |
| Mandatory | msisdn |
GET / POST |
Mobile number in international format without a leading + or leading 0.
The value must be numeric and between 9 and 15 digits.
Example: 12025550100.
|
MNP Success Response
On success, the API returns a JSON object containing a results array.
The result includes the submitted MSISDN, country, operator, number type, MCC/MNC,
roaming status, provider status, provider error code/description, and portability status.
{
"results": [
{
"msisdn": "12025550100",
"country": "United States",
"err_desc": "No Error",
"operator": "Example Operator",
"type": "mobile",
"mccmnc": "310000",
"is_roaming": "false",
"err_code": "0",
"status": "DELIVERED",
"is_ported": "false"
}
]
}
MNP Response Fields
| Field | Description |
|---|---|
results |
An array containing the MNP/HLR lookup result. |
msisdn |
The submitted mobile number returned by the lookup provider. |
country |
The country detected from the number issuing information. |
err_desc |
The provider error description, when returned by the lookup provider. |
operator |
The detected mobile network/operator name. |
type |
The number type returned by the lookup provider, for example mobile or other available type. |
mccmnc |
The combined Mobile Country Code and Mobile Network Code. |
is_roaming |
Indicates whether the number is reported as roaming by the lookup provider. |
err_code |
The provider error code returned with the lookup result. |
status |
The provider status returned for the lookup request. |
is_ported |
Indicates whether the number is reported as ported by the lookup provider. |
MNP Error Codes
Failed requests return a plain text response code. These codes help identify whether the issue is related to request format, authentication, balance, provider availability, or a temporary system error.
| Response | Status | Description |
|---|---|---|
00 |
Missing Parameters | No parameters were submitted. |
01 |
Username Error | The username parameter is missing or empty. |
02 |
Password Error | The password parameter is missing or empty. |
03 |
MSISDN Error | The MSISDN parameter is missing or empty. |
04 |
Invalid MSISDN |
The MSISDN format is invalid. It must be numeric, must not start with 0,
and must be between 9 and 15 digits.
|
05 |
Username Error | The username length is invalid. Username must be less than 30 characters. |
06 |
Password Error | The password length is invalid. Password must be less than 20 characters. |
07 |
Invalid Characters | Invalid characters were detected in one or more request parameters. |
08 |
Invalid Request | A parameter was sent more than once or sent in both GET and POST. |
09 |
Authentication Failed | Authentication failed. The username/password is incorrect, the account is not active, the account is a demo account, or the account is not allowed to use this API. |
10 |
Insufficient Credits | The account does not have enough available balance to complete the MNP lookup. |
12 |
Provider Error | The MNP/HLR provider did not return a valid response, returned an empty response, or the provider response could not be processed. |
99 |
System Error | Temporary system error. The request could not be processed due to an internal server, database, reporting, or routing issue. Please retry later. |
MNV Number Validation API
Use the MNV API to validate mobile numbers, improve contact database quality, identify invalid entries, and reduce wasted SMS attempts caused by incorrectly formatted or unsupported numbers.
Endpoint
The endpoint supports both GET and POST. POST is recommended because it keeps your credentials out of the URL, browser history, and most server/proxy logs.
https://api.bulksmsonline.co/mnv?username=XXXX&password=YYYYY&msisdn=12025550100
curl -X POST https://api.bulksmsonline.co/mnv \
-d "username=XXXX" \
-d "password=YYYYY" \
-d "msisdn=12025550100"
MNV Request Parameters
| Presence | Parameter | Method | Description |
|---|---|---|---|
| Mandatory | username |
GET / POST | Your BulkSMSOnline account username. |
| Mandatory | password |
GET / POST | Your BulkSMSOnline account password. |
| Mandatory | msisdn |
GET / POST |
Mobile number in international format without a leading + or leading 0.
The value must be numeric and between 9 and 15 digits.
Example: 12025550100.
|
MNV Success Response
On success, the API returns a JSON object containing the detected country, network, operator, MCC/MNC, number type, network type, and the submitted MSISDN.
{
"Country": "United States",
"ISO3166_2": "US",
"CC": "1",
"NetName": "Example Network",
"MCC": "310",
"MNC": "000",
"OPERATOR": "Example Operator",
"Type": "Mobile",
"NetType": "GSM",
"MSISDN": "12025550100"
}
MNV Response Fields
| Field | Description |
|---|---|
Country |
The detected country name for the submitted MSISDN. |
ISO3166_2 |
The two-letter ISO country code. |
CC |
The country calling code. |
NetName |
The detected network name. |
MCC |
The Mobile Country Code. |
MNC |
The Mobile Network Code. |
OPERATOR |
The detected mobile operator name. |
Type |
The number type returned by the validation database. |
NetType |
The detected network type, when available. |
MSISDN |
The submitted mobile number. |
MNV Error Codes
Failed requests return a plain text response code. These codes help you identify whether the issue is related to request format, authentication, balance, number validation, or a temporary system error.
| Response | Status | Description |
|---|---|---|
00 |
Missing Parameters | No parameters were submitted. |
01 |
Username Error | The username parameter is missing or empty. |
02 |
Password Error | The password parameter is missing or empty. |
03 |
MSISDN Error | The MSISDN parameter is missing or empty. |
04 |
Invalid MSISDN |
The MSISDN format is invalid. It must be numeric, must not start with 0,
and must be between 9 and 15 digits.
|
05 |
Username Error | The username length is invalid. Username must be less than 30 characters. |
06 |
Password Error | The password length is invalid. Password must be less than 20 characters. |
07 |
Invalid Characters | Invalid characters were detected in one or more request parameters. |
08 |
Invalid Request | A parameter was sent more than once or sent in both GET and POST. |
09 |
Authentication Failed | Authentication failed. The username/password is incorrect, the account is not active, the account is a demo account, or the account is not allowed to use this API. |
10 |
Insufficient Credits | The account does not have enough available balance to complete the MNV lookup. |
11 |
No MNV Data | The number format is valid, but no MNV data was found for the submitted MSISDN. |
99 |
System Error | Temporary system error. The request could not be processed due to an internal server, database, or routing issue. Please retry later. |
Code Samples
Use these server-side examples as a starting point for integrating BulkSMSOnline in your application. Never expose your API username, password, or REST token in frontend JavaScript, public repositories, or mobile app bundles.
HTTP SMS API
Sends a text SMS using the form-based HTTP endpoint. The API returns plain text such as
OK|MESSAGE_ID for accepted submissions.
<?php
$endpoint = 'https://api.bulksmsonline.co/smsapi';
$payload = [
'username' => getenv('BULKSMS_USERNAME') ?: 'YOUR_USERNAME',
'password' => getenv('BULKSMS_PASSWORD') ?: 'YOUR_PASSWORD',
'type' => 't',
'to' => '1234567890',
'source' => 'YourBrand',
'message' => 'Hello from BulkSMSOnline'
];
$ch = curl_init($endpoint);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($payload),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'Content-Type: application/x-www-form-urlencoded'
],
]);
$response = curl_exec($ch);
if ($response === false) {
throw new RuntimeException('cURL error: ' . curl_error($ch));
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode < 200 || $httpCode >= 300) {
throw new RuntimeException("HTTP error {$httpCode}: {$response}");
}
if (str_starts_with($response, 'OK|')) {
$messageId = substr($response, 3);
echo "Message accepted. ID: {$messageId}" . PHP_EOL;
} else {
echo "API rejected request. Response: {$response}" . PHP_EOL;
}
using System.Net.Http;
var endpoint = "https://api.bulksmsonline.co/smsapi";
var payload = new Dictionary<string, string>
{
["username"] = Environment.GetEnvironmentVariable("BULKSMS_USERNAME") ?? "YOUR_USERNAME",
["password"] = Environment.GetEnvironmentVariable("BULKSMS_PASSWORD") ?? "YOUR_PASSWORD",
["type"] = "t",
["to"] = "1234567890",
["source"] = "YourBrand",
["message"] = "Hello from BulkSMSOnline"
};
using var http = new HttpClient
{
Timeout = TimeSpan.FromSeconds(30)
};
using var content = new FormUrlEncodedContent(payload);
using var response = await http.PostAsync(endpoint, content);
var body = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
throw new HttpRequestException($"HTTP {(int)response.StatusCode}: {body}");
}
if (body.StartsWith("OK|", StringComparison.OrdinalIgnoreCase))
{
var messageId = body.Split('|', 2)[1];
Console.WriteLine($"Message accepted. ID: {messageId}");
}
else
{
Console.WriteLine($"API rejected request. Response: {body}");
}
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Map;
import java.util.stream.Collectors;
public class SendHttpSms {
public static void main(String[] args) throws Exception {
String endpoint = "https://api.bulksmsonline.co/smsapi";
Map<String, String> payload = Map.of(
"username", getenvOrDefault("BULKSMS_USERNAME", "YOUR_USERNAME"),
"password", getenvOrDefault("BULKSMS_PASSWORD", "YOUR_PASSWORD"),
"type", "t",
"to", "1234567890",
"source", "YourBrand",
"message", "Hello from BulkSMSOnline"
);
String formBody = payload.entrySet()
.stream()
.map(e -> encode(e.getKey()) + "=" + encode(e.getValue()))
.collect(Collectors.joining("&"));
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(15))
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(endpoint))
.timeout(Duration.ofSeconds(30))
.header("Content-Type", "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(formBody))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() < 200 || response.statusCode() >= 300) {
throw new RuntimeException("HTTP " + response.statusCode() + ": " + response.body());
}
if (response.body().startsWith("OK|")) {
String messageId = response.body().split("\\|", 2)[1];
System.out.println("Message accepted. ID: " + messageId);
} else {
System.out.println("API rejected request. Response: " + response.body());
}
}
private static String encode(String value) {
return URLEncoder.encode(value, StandardCharsets.UTF_8);
}
private static String getenvOrDefault(String key, String fallback) {
String value = System.getenv(key);
return value == null || value.isBlank() ? fallback : value;
}
}
REST SMS API
Generates a REST token first, then sends a JSON SMS request using the required
token HTTP header.
<?php
$username = getenv('BULKSMS_USERNAME') ?: 'YOUR_USERNAME';
$password = getenv('BULKSMS_PASSWORD') ?: 'YOUR_PASSWORD';
$baseUrl = 'https://api.bulksmsonline.co/rest/api/v1';
$tokenUrl = $baseUrl
. '/sms/gettoken/username/' . rawurlencode($username)
. '/password/' . rawurlencode($password);
$tokenResponse = requestJson('GET', $tokenUrl);
$token = $tokenResponse['token'] ?? null;
if (!$token) {
throw new RuntimeException('Token was not returned by REST API.');
}
$smsPayload = [
'from' => 'YourBrand',
'to' => ['1234567890'],
'type' => 'Text',
'content' => 'Hello from BulkSMSOnline REST API',
'sendDateTime' => null
];
$sendResponse = requestJson('POST', $baseUrl . '/sms/send/', $smsPayload, [
'token: ' . $token,
'Content-Type: application/json',
'Accept: application/json'
]);
print_r($sendResponse);
function requestJson(string $method, string $url, ?array $payload = null, array $headers = []): array
{
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => $headers ?: ['Accept: application/json'],
]);
if ($payload !== null) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload, JSON_THROW_ON_ERROR));
}
$response = curl_exec($ch);
if ($response === false) {
throw new RuntimeException('cURL error: ' . curl_error($ch));
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode < 200 || $httpCode >= 300) {
throw new RuntimeException("HTTP error {$httpCode}: {$response}");
}
return json_decode($response, true, flags: JSON_THROW_ON_ERROR);
}
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json.Serialization;
var username = Environment.GetEnvironmentVariable("BULKSMS_USERNAME") ?? "YOUR_USERNAME";
var password = Environment.GetEnvironmentVariable("BULKSMS_PASSWORD") ?? "YOUR_PASSWORD";
var baseUrl = "https://api.bulksmsonline.co/rest/api/v1";
using var http = new HttpClient
{
Timeout = TimeSpan.FromSeconds(30)
};
var tokenUrl =
$"{baseUrl}/sms/gettoken/username/{Uri.EscapeDataString(username)}/password/{Uri.EscapeDataString(password)}";
using var tokenResponse = await http.GetAsync(tokenUrl);
var tokenBody = await tokenResponse.Content.ReadAsStringAsync();
if (!tokenResponse.IsSuccessStatusCode)
{
throw new HttpRequestException($"Token request failed: {(int)tokenResponse.StatusCode} {tokenBody}");
}
var tokenResult = await tokenResponse.Content.ReadFromJsonAsync<TokenResponse>();
var token = tokenResult?.Token;
if (string.IsNullOrWhiteSpace(token))
{
throw new InvalidOperationException("Token was not returned by REST API.");
}
var smsPayload = new
{
from = "YourBrand",
to = new[] { "1234567890" },
type = "Text",
content = "Hello from BulkSMSOnline REST API",
sendDateTime = (string?)null
};
using var sendRequest = new HttpRequestMessage(HttpMethod.Post, $"{baseUrl}/sms/send/")
{
Content = JsonContent.Create(smsPayload)
};
sendRequest.Headers.Add("token", token);
sendRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
using var sendResponse = await http.SendAsync(sendRequest);
var sendBody = await sendResponse.Content.ReadAsStringAsync();
if (!sendResponse.IsSuccessStatusCode)
{
throw new HttpRequestException($"Send request failed: {(int)sendResponse.StatusCode} {sendBody}");
}
Console.WriteLine(sendBody);
public sealed record TokenResponse(
[property: JsonPropertyName("token")] string Token
);
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.List;
import java.util.Map;
public class SendRestSms {
public static void main(String[] args) throws Exception {
String username = getenvOrDefault("BULKSMS_USERNAME", "YOUR_USERNAME");
String password = getenvOrDefault("BULKSMS_PASSWORD", "YOUR_PASSWORD");
String baseUrl = "https://api.bulksmsonline.co/rest/api/v1";
ObjectMapper mapper = new ObjectMapper();
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(15))
.build();
String tokenUrl = baseUrl
+ "/sms/gettoken/username/" + encodePath(username)
+ "/password/" + encodePath(password);
HttpRequest tokenRequest = HttpRequest.newBuilder()
.uri(URI.create(tokenUrl))
.timeout(Duration.ofSeconds(30))
.GET()
.build();
HttpResponse<String> tokenResponse =
client.send(tokenRequest, HttpResponse.BodyHandlers.ofString());
if (tokenResponse.statusCode() < 200 || tokenResponse.statusCode() >= 300) {
throw new RuntimeException("Token request failed: " + tokenResponse.body());
}
JsonNode tokenJson = mapper.readTree(tokenResponse.body());
String token = tokenJson.path("token").asText();
if (token == null || token.isBlank()) {
throw new RuntimeException("Token was not returned by REST API.");
}
Map<String, Object> smsPayload = Map.of(
"from", "YourBrand",
"to", List.of("1234567890"),
"type", "Text",
"content", "Hello from BulkSMSOnline REST API",
"sendDateTime", null
);
String jsonBody = mapper.writeValueAsString(smsPayload);
HttpRequest sendRequest = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/sms/send/"))
.timeout(Duration.ofSeconds(30))
.header("token", token)
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.build();
HttpResponse<String> sendResponse =
client.send(sendRequest, HttpResponse.BodyHandlers.ofString());
if (sendResponse.statusCode() < 200 || sendResponse.statusCode() >= 300) {
throw new RuntimeException("Send request failed: " + sendResponse.body());
}
System.out.println(sendResponse.body());
}
private static String encodePath(String value) {
return URLEncoder.encode(value, StandardCharsets.UTF_8).replace("+", "%20");
}
private static String getenvOrDefault(String key, String fallback) {
String value = System.getenv(key);
return value == null || value.isBlank() ? fallback : value;
}
}
MNP / HLR Lookup API
Checks mobile number portability, network/operator data, roaming status, and HLR-level lookup information.
<?php
$endpoint = 'https://api.bulksmsonline.co/mnp';
$payload = [
'username' => getenv('BULKSMS_USERNAME') ?: 'YOUR_USERNAME',
'password' => getenv('BULKSMS_PASSWORD') ?: 'YOUR_PASSWORD',
'msisdn' => '12025550100'
];
$ch = curl_init($endpoint);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($payload),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'Content-Type: application/x-www-form-urlencoded',
'Accept: application/json'
],
]);
$response = curl_exec($ch);
if ($response === false) {
throw new RuntimeException('cURL error: ' . curl_error($ch));
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode < 200 || $httpCode >= 300) {
throw new RuntimeException("HTTP error {$httpCode}: {$response}");
}
if (str_starts_with(trim($response), '{')) {
$data = json_decode($response, true, flags: JSON_THROW_ON_ERROR);
print_r($data);
} else {
echo "MNP lookup error code: {$response}" . PHP_EOL;
}
using System.Text.Json;
var endpoint = "https://api.bulksmsonline.co/mnp";
var payload = new Dictionary<string, string>
{
["username"] = Environment.GetEnvironmentVariable("BULKSMS_USERNAME") ?? "YOUR_USERNAME",
["password"] = Environment.GetEnvironmentVariable("BULKSMS_PASSWORD") ?? "YOUR_PASSWORD",
["msisdn"] = "12025550100"
};
using var http = new HttpClient
{
Timeout = TimeSpan.FromSeconds(30)
};
using var content = new FormUrlEncodedContent(payload);
using var response = await http.PostAsync(endpoint, content);
var body = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
throw new HttpRequestException($"HTTP {(int)response.StatusCode}: {body}");
}
if (body.TrimStart().StartsWith("{", StringComparison.Ordinal))
{
using var json = JsonDocument.Parse(body);
Console.WriteLine(json.RootElement.ToString());
}
else
{
Console.WriteLine($"MNP lookup error code: {body}");
}
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Map;
import java.util.stream.Collectors;
public class MnpLookup {
public static void main(String[] args) throws Exception {
String endpoint = "https://api.bulksmsonline.co/mnp";
Map<String, String> payload = Map.of(
"username", getenvOrDefault("BULKSMS_USERNAME", "YOUR_USERNAME"),
"password", getenvOrDefault("BULKSMS_PASSWORD", "YOUR_PASSWORD"),
"msisdn", "12025550100"
);
String formBody = payload.entrySet()
.stream()
.map(e -> encode(e.getKey()) + "=" + encode(e.getValue()))
.collect(Collectors.joining("&"));
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(15))
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(endpoint))
.timeout(Duration.ofSeconds(30))
.header("Content-Type", "application/x-www-form-urlencoded")
.header("Accept", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(formBody))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() < 200 || response.statusCode() >= 300) {
throw new RuntimeException("HTTP " + response.statusCode() + ": " + response.body());
}
String body = response.body().trim();
if (body.startsWith("{")) {
System.out.println("MNP lookup result: " + body);
} else {
System.out.println("MNP lookup error code: " + body);
}
}
private static String encode(String value) {
return URLEncoder.encode(value, StandardCharsets.UTF_8);
}
private static String getenvOrDefault(String key, String fallback) {
String value = System.getenv(key);
return value == null || value.isBlank() ? fallback : value;
}
}
MNV Number Validation API
Validates a mobile number and returns country, operator, MCC/MNC, number type, network type, and normalized MSISDN data.
<?php
$endpoint = 'https://api.bulksmsonline.co/mnv';
$payload = [
'username' => getenv('BULKSMS_USERNAME') ?: 'YOUR_USERNAME',
'password' => getenv('BULKSMS_PASSWORD') ?: 'YOUR_PASSWORD',
'msisdn' => '12025550100'
];
$ch = curl_init($endpoint);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($payload),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'Content-Type: application/x-www-form-urlencoded',
'Accept: application/json'
],
]);
$response = curl_exec($ch);
if ($response === false) {
throw new RuntimeException('cURL error: ' . curl_error($ch));
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode < 200 || $httpCode >= 300) {
throw new RuntimeException("HTTP error {$httpCode}: {$response}");
}
if (str_starts_with(trim($response), '{')) {
$data = json_decode($response, true, flags: JSON_THROW_ON_ERROR);
print_r($data);
} else {
echo "MNV validation error code: {$response}" . PHP_EOL;
}
using System.Text.Json;
var endpoint = "https://api.bulksmsonline.co/mnv";
var payload = new Dictionary<string, string>
{
["username"] = Environment.GetEnvironmentVariable("BULKSMS_USERNAME") ?? "YOUR_USERNAME",
["password"] = Environment.GetEnvironmentVariable("BULKSMS_PASSWORD") ?? "YOUR_PASSWORD",
["msisdn"] = "12025550100"
};
using var http = new HttpClient
{
Timeout = TimeSpan.FromSeconds(30)
};
using var content = new FormUrlEncodedContent(payload);
using var response = await http.PostAsync(endpoint, content);
var body = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
throw new HttpRequestException($"HTTP {(int)response.StatusCode}: {body}");
}
if (body.TrimStart().StartsWith("{", StringComparison.Ordinal))
{
using var json = JsonDocument.Parse(body);
Console.WriteLine(json.RootElement.ToString());
}
else
{
Console.WriteLine($"MNV validation error code: {body}");
}
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Map;
import java.util.stream.Collectors;
public class MnvValidation {
public static void main(String[] args) throws Exception {
String endpoint = "https://api.bulksmsonline.co/mnv";
Map<String, String> payload = Map.of(
"username", getenvOrDefault("BULKSMS_USERNAME", "YOUR_USERNAME"),
"password", getenvOrDefault("BULKSMS_PASSWORD", "YOUR_PASSWORD"),
"msisdn", "12025550100"
);
String formBody = payload.entrySet()
.stream()
.map(e -> encode(e.getKey()) + "=" + encode(e.getValue()))
.collect(Collectors.joining("&"));
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(15))
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(endpoint))
.timeout(Duration.ofSeconds(30))
.header("Content-Type", "application/x-www-form-urlencoded")
.header("Accept", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(formBody))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() < 200 || response.statusCode() >= 300) {
throw new RuntimeException("HTTP " + response.statusCode() + ": " + response.body());
}
String body = response.body().trim();
if (body.startsWith("{")) {
System.out.println("MNV validation result: " + body);
} else {
System.out.println("MNV validation error code: " + body);
}
}
private static String encode(String value) {
return URLEncoder.encode(value, StandardCharsets.UTF_8);
}
private static String getenvOrDefault(String key, String fallback) {
String value = System.getenv(key);
return value == null || value.isBlank() ? fallback : value;
}
}
Integration Best Practices
Do not call SMS APIs directly from public browser JavaScript.
Encode message content and special characters correctly before sending.
Save returned message IDs to match delivery reports later.
Retry safely with backoff when throttling or temporary service errors occur.
Use MNV and MNP lookup where needed to improve routing and reduce failed sends.
Keep request IDs, message IDs, responses, and callback payloads for support and reconciliation.
Developer API FAQ
Quick answers for developers integrating BulkSMSOnline HTTP API, REST API, SMPP, delivery reports, MNP/HLR lookup, number validation, and account balance checks.
API Choice
Which API should I use to send SMS?
HTTP API
When should I use the HTTP SMS API?
REST API
When should I use the REST SMS API?
SMPP
When should I use SMPP instead of HTTP or REST?
deliver_sm. SMPP access must be approved and your server IP must be whitelisted.
Auth
How does authentication work?
token HTTP header. SMPP uses SMPP credentials provided after approval.
Security
Can I call the API directly from frontend JavaScript?
Recipients
How many recipients can I send in one request?
Rate Limit
What happens if I send too fast?
DLR
Can I receive delivery reports?
Webhook
How should my DLR webhook respond?
Retry
Should I retry failed API requests?
Sender ID
What sender ID format should I use?
Encoding
Should I send Text or Unicode SMS?
Schedule
Can I schedule SMS for later?
Balance
Can I check my balance through API?
MNP / HLR
Does BulkSMSOnline support MNP or HLR lookup?
MNV
Does BulkSMSOnline support mobile number validation?
Format
What number format should I send?
00.
Errors
How should I handle API error codes?
Production
What should I prepare before going live?
Need Help With Your SMS API Integration?
Our support team can help you choose the right API, test delivery, configure SMPP access, set up delivery report callbacks, and troubleshoot production integration issues.