Hello! 👋
Message Sent ✓
Delivered ✓✓
200+ Countries
Bulk SMS 📨
API Ready
SMS
Connecting worldwide
Login Sign Up Free
Chat on WhatsApp Send us an Email
Developer Documentation

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.

Example Request

HTTP SMS API

GET https://api.bulksmsonline.co/smsapi
username YOUR_USERNAME
password YOUR_PASSWORD
type t
to 1234567890
source YourBrand
message Hello from BulkSMSOnline

Getting Started

Select an API category from the left menu to view only the related documentation.

Overview

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.

HTTP API

Simple URL-based SMS sending for fast integration and legacy systems.

REST API

JSON-based API for modern applications, backend services, and scalable workflows.

SMPP API

Low-latency SMPP connectivity for high-volume and carrier-grade integrations.

Quick Start

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

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.

HTTP API

Uses username and password parameters in the API request.

REST API

Generate a token first, then include the token with each SMS request.

SMPP API

Uses SMPP username, password, host, port, bind type, and IP whitelist approval.

Webhooks

Use your configured callback URL to receive delivery status updates from BulkSMSOnline.

HTTP API

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

HTTP SMS Endpoint GET / POST
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.
  • t —-- Plain text message for English/Latin content. The message must be URL-encoded and should use GSM 03.38 character encoding.
  • u —-- Unicode message for languages such as Arabic, Chinese, or other non-Latin scripts.
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.
  • Numeric sender ID: maximum 18 digits.
  • Alphanumeric sender ID: maximum 11 characters.
  • Additional restrictions may apply depending on the SMSC or destination network.
Mandatory message The SMS message body.
  • For plain text messages, such as English or Latin-based content, the message must be URL-encoded and should use GSM 03.38 character encoding.
  • For Unicode messages, such as Arabic, Chinese, or other non-Latin languages, the message text must be encoded in UTF-16BE before sending.
Optional scheduled Schedule the SMS to be sent at a future date and time.
  • The date/time must be provided in ISO 8601 format: yyyy-MM-ddTHH:mm:ss
  • The value must be URL-encoded when sent via API.
  • The scheduled time must be based on the UTC-04:00 timezone.
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.

Tip: Always store the returned message ID from successful submissions. It can be used later for delivery tracking, reporting, support checks, or matching delivery reports.
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

Aa Plain Text SMS Example
GET

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
Unicode SMS Example
GET

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
Original Unicode text مرحبا
UTF-16BE encoded value 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.

Balance Endpoint GET / POST
https://api.bulksmsonline.co/balance?username=XXXX&password=YYYYY
POST Example Recommended
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.

Successful Response Example text/plain
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.
Security note: We recommend using POST for this endpoint because it keeps credentials out of the URL, browser history, and most server/proxy access logs.
REST API

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.

Versioned REST Base URL HTTPS
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.

Token Endpoint GET
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

HTTP 200 Response application/json
{
  "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.

Send SMS Endpoint POST
POST https://api.bulksmsonline.co/rest/api/v1/sms/send/

Required Headers

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

JSON Request Object application/json
{
  "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 Example POST
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.

Example: If one REST request contains 30 destination numbers in the 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.
Important: Token generation uses your account username and password, but sending SMS through the REST API requires the generated token only. Do not expose your account password in client-side JavaScript, mobile apps, public repositories, or browser-based integrations.
Swagger

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

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.

Access required: SMPP access is available for approved customers. To connect, you must request SMPP credentials from support and provide your server IP address for firewall whitelisting before using the service.

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

Default Throughput

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.

Maximum Available Throughput

SMPP can support high-volume sending up to 60 messages per second where enabled for the account and supported by the destination route.

Window Size

Recommended default window size is 5 open requests. This means up to 5 submit requests may be waiting for responses at the same time.

Enquire Link

Send enquire_link every 60 seconds to keep the SMPP connection alive and detect broken sessions.

Throttling note: SMPP throughput is calculated by MT messages per second. If the allowed sending rate is exceeded, the SMSC may return a throttling error such as 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
0x000000000No Error
0x000000011Message length is invalid
0x000000022Command length is invalid
0x000000033Invalid Command ID
0x000000044Incorrect BIND Status for given command
0x000000055ESME already in bound state
0x000000066Invalid Priority Flag
0x000000077Invalid Registered Delivery Flag
0x000000088System Error
0x00000009-Reserved
0x0000000A10Invalid Source Address
0x0000000B11Invalid Destination Address
0x0000000C12Message ID is invalid
0x0000000D13Bind Failed
0x0000000E14Invalid Password
0x0000000F15Invalid System ID
0x0000001016Reserved
0x0000001117Cancel SM Failed
0x00000012-Reserved
0x0000001319Replace SM Failed
0x0000001420Message Queue Full
0x0000001521Invalid Service Type
0x00000016-Reserved through 0x00000032
0x0000003351Invalid number of destinations
0x0000003452Invalid Distribution List name
0x0000003553Reserved through 0x0000003F
0x0000004064Destination flag is invalid for submit_multi
0x00000041-Reserved
0x0000004266Invalid submit with replace request; submit_sm with replace_if_present_flag set
0x0000004367Invalid esm_class field data
0x0000004468Cannot submit to distribution list
0x0000004569submit_sm or submit_multi failed
0x00000046-Reserved through 0x00000047
0x0000004872Invalid Source Address TON
0x0000004973Invalid Source Address NPI
0x0000005080Invalid Destination Address TON
0x0000005181Invalid Destination Address NPI
0x00000052-Reserved
0x0000005383Invalid system_type field
0x0000005484Invalid replace_if_present flag
0x0000005585Invalid number of messages
0x00000056-Reserved through 0x00000057
0x0000005888Throttling error; ESME has exceeded allowed message limits
0x0000005989Reserved through 0x00000060
0x0000006197Invalid Scheduled Delivery Time
0x0000006298Invalid message validity period / expiry time
0x0000006399Predefined Message Invalid or Not Found
0x00000064100ESME Receiver Temporary Application Error Code
0x00000065101ESME Receiver Permanent Application Error Code
0x00000066102ESME Receiver Reject Message Error Code
0x00000067103query_sm request failed
0x00000068104Reserved through 0x000000BF
0x000000C0192Error in the optional part of the PDU body
0x000000C1193Optional parameter not allowed
0x000000C2194Invalid parameter length
0x000000C3195Expected optional parameter missing
0x000000C4196Invalid optional parameter value
0x000000C5 - 0x000000FD-Reserved
0x000000FE245Delivery Failure, used for data_sm_resp
0x000000FF255Unknown Error
0x00000100 - 0x000003FF-Reserved for SMPP extension
Delivery Reports

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.
Note: Some routes may return intermediate updates before the final delivery status. Your system should update the same message record using the returned smsid instead of creating duplicate delivery records.
Webhook

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.

Where to set your webhook URL: Log in to your BulkSMSOnline account, open your account settings, and add your callback URL under the DLR Through Web Notification section.

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.

Public URL

Your webhook endpoint must be accessible from the public internet. HTTPS is recommended for production integrations.

Allowed Methods

Your endpoint should accept POST, GET, and HEAD. Process the delivery report only when the request method is POST.

HTTP 200 Required

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.

Fast Response

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.

Example POST Body application/x-www-form-urlencoded
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.

Expected Response HTTP
HTTP/1.1 200 OK
Important: Because failed callbacks are retried, your webhook should be idempotent. This means your system should safely handle the same 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.

Recommended: Use HTTPS, keep your webhook endpoint lightweight, allow POST, GET, and HEAD, and return HTTP 200 only after your application has safely received the callback.
MNP Lookup

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.

MNP Lookup Endpoint GET / POST
https://api.bulksmsonline.co/mnp?username=XXXX&password=YYYYY&msisdn=12025550100
POST Example Recommended
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.

Successful Response Example application/json
{
            "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.
Billing note: The MNP lookup cost is deducted only after the request format is accepted, the account is authenticated, sufficient credits are available, and the MNP/HLR provider returns a readable lookup result.
Number Validation

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.

MNV Endpoint GET / POST
https://api.bulksmsonline.co/mnv?username=XXXX&password=YYYYY&msisdn=12025550100
POST Example Recommended
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.

Successful Response Example application/json
{
            "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.
Billing note: The MNV lookup cost is deducted only after the number format is accepted, the account is authenticated, sufficient credits are available, and MNV data is successfully found.
Examples

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.

Production note: Store credentials in environment variables, log the API response, save returned message IDs, and add retry/backoff only for temporary failures.

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.

POST https://api.bulksmsonline.co/smsapi
PHP 8.1+ / cURL
<?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;
    }
C# / .NET 8 HttpClient
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}");
    }
Java 17+ HttpClient
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.

POST /rest/api/v1/sms/send/
PHP 8.1+ / cURL
<?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);
    }
C# / .NET 8 HttpClient
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
    );
Java 17+ HttpClient + Jackson
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.

POST https://api.bulksmsonline.co/mnp
PHP 8.1+ / cURL
<?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;
    }
C# / .NET 8 HttpClient
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}");
    }
Java 17+ HttpClient
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.

POST https://api.bulksmsonline.co/mnv
PHP 8.1+ / cURL
<?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;
    }
C# / .NET 8 HttpClient
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}");
    }
Java 17+ HttpClient
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;
        }
    }
Best Practices

Integration Best Practices

Use server-side calls only

Do not call SMS APIs directly from public browser JavaScript.

URL encode messages

Encode message content and special characters correctly before sending.

Store message IDs

Save returned message IDs to match delivery reports later.

Handle rate limits

Retry safely with backoff when throttling or temporary service errors occur.

Validate numbers

Use MNV and MNP lookup where needed to improve routing and reduce failed sends.

Log API responses

Keep request IDs, message IDs, responses, and callback payloads for support and reconciliation.

FAQ

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?

Use the HTTP API for simple server-side integrations, the REST API for modern JSON-based applications, and SMPP for high-volume or carrier-grade connections that need persistent protocol-level connectivity.
HTTP API

When should I use the HTTP SMS API?

Use the HTTP API when you need a fast and simple integration using GET or POST requests. POST is recommended because it keeps credentials out of URLs, browser history, and most access logs.
REST API

When should I use the REST SMS API?

Use the REST API for backend applications that prefer JSON request bodies, JSON responses, token-based authentication, structured error handling, and cleaner integration with modern systems.
SMPP

When should I use SMPP instead of HTTP or REST?

Use SMPP if you send high-volume SMS traffic, need lower latency, want transmitter/receiver/transceiver binds, or need delivery reports through SMPP deliver_sm. SMPP access must be approved and your server IP must be whitelisted.
Auth

How does authentication work?

The HTTP API, balance API, MNP, and MNV use account username and password. The REST API generates a token first, then uses that token in the token HTTP header. SMPP uses SMPP credentials provided after approval.
Security

Can I call the API directly from frontend JavaScript?

No. Always call BulkSMSOnline APIs from your backend server. API usernames, passwords, tokens, and SMPP credentials must never be exposed in browser code, mobile apps, public Git repositories, or client-side scripts.
Recipients

How many recipients can I send in one request?

A single HTTP or REST SMS request can include up to 30 destination numbers. For larger campaigns, split your list into batches and control your sending speed to stay within the allowed throughput.
Rate Limit

What happens if I send too fast?

Requests may be throttled or rejected when the allowed sending rate is exceeded. Use a queue on your side, send in controlled batches, and retry temporary failures with a short backoff instead of resending immediately.
DLR

Can I receive delivery reports?

Yes. Delivery reports help you track message statuses such as delivered, failed, expired, undeliverable, or rejected. You can receive status updates through webhook callbacks, and SMPP customers can receive DLRs through SMPP where enabled.
Webhook

How should my DLR webhook respond?

Your webhook should be publicly reachable over HTTPS, accept POST requests, store the callback quickly, and return HTTP 200 after receiving it. Process heavier database updates or external calls asynchronously.
Retry

Should I retry failed API requests?

Retry only temporary errors such as server errors, service unavailable responses, or network timeouts. Do not blindly retry validation errors, authentication errors, insufficient balance errors, invalid sender ID errors, or rejected message content.
Sender ID

What sender ID format should I use?

Alphanumeric sender IDs can contain up to 11 characters. Numeric sender IDs can contain up to 18 digits. Availability may depend on the destination country, route, operator rules, and sender registration requirements.
Encoding

Should I send Text or Unicode SMS?

Use plain text for English or Latin-based GSM messages. Use Unicode for Arabic, Chinese, Cyrillic, emojis, and other non-Latin content. Unicode messages use fewer characters per SMS part than standard GSM text.
Schedule

Can I schedule SMS for later?

Yes. Scheduled SMS is supported by using the scheduled date/time field in the API request. Use the documented ISO date-time format and confirm the expected timezone before sending production campaigns.
Balance

Can I check my balance through API?

Yes. Use the balance API to check your available SMS balance from your backend system. POST is recommended because it avoids placing credentials in the URL.
MNP / HLR

Does BulkSMSOnline support MNP or HLR lookup?

Yes. The MNP/HLR lookup API can help check portability, roaming status, operator, country, MCC/MNC, provider status, and other network-level details for a mobile number.
MNV

Does BulkSMSOnline support mobile number validation?

Yes. The MNV API helps validate mobile numbers and can return details such as country, ISO code, country calling code, network name, MCC, MNC, operator, number type, network type, and normalized MSISDN.
Format

What number format should I send?

Send destination numbers in international MSISDN format. For best results, use digits only without spaces, brackets, dashes, or the international dialing prefix 00.
Errors

How should I handle API error codes?

Log the full request reference, timestamp, destination number, sender ID, message ID if available, HTTP status, and API response code. Fix permanent errors before retrying and contact support with the logged details if needed.
Production

What should I prepare before going live?

Confirm your route, sender ID format, number format, message encoding, account balance, DLR webhook, retry logic, logging, rate limits, and content compliance before sending production traffic.
Need more answers? For general SMS, billing, route, account, and platform questions, visit our full FAQ page.
Visit FAQ Page
Support

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.