BulkieMsg Developer Docs
bulkiemsg.com/api/v1 Dashboard
REST API · v1

API Reference

The BulkieMsg API lets you send high-volume SMS and WhatsApp messages, check your credit balance, and manage sender identities — from any language or platform.

HTTPS only
JSON responses
API key auth
Real-time delivery

All requests go to the base URL below. Every response is JSON. Every request body must include Content-Type: application/json.

BASE URL
https://bulkiemsg.com/api/v1
ℹ️ All endpoints return a JSON object with a success boolean. On error, an error field describes what went wrong.

Authentication

Every request must include your API key. Generate one from your BulkieMsg dashboard under Settings → API Keys. Keys look like bm_live_xxxxxxxxxxxxxxxx.

Pass the key via the Authorization header (preferred) or X-API-Key:

Authorization header — preferred
Authorization: Bearer bm_live_your_api_key_here
X-API-Key header — alternative
X-API-Key: bm_live_your_api_key_here
⚠️ Keep your API key secret. Never commit it to source control or expose it in client-side JavaScript.

Quick Start

Generate your API key

Log in, go to Settings → API Keys, and click Generate Key. Copy it — it's shown only once.

Get a Sender ID approved

Go to SMS → Sender IDs in your dashboard and request a branded ID (e.g. your company name). You cannot send SMS without an approved Sender ID.

Send your first message

bash
curl -X POST https://bulkiemsg.com/api/v1/sms/send \
  -H "Authorization: Bearer bm_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sender_id": "YourBrand",
    "message":   "Hello! Your order has shipped.",
    "to":        ["233201234567"]
  }'
php
$ch = curl_init('https://bulkiemsg.com/api/v1/sms/send');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer bm_live_YOUR_KEY',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'sender_id' => 'YourBrand',
        'message'   => 'Hello! Your order has shipped.',
        'to'        => ['233201234567'],
    ]),
]);
$res = json_decode(curl_exec($ch), true);
var_dump($res);
python
import requests

res = requests.post(
    "https://bulkiemsg.com/api/v1/sms/send",
    headers={
        "Authorization": "Bearer bm_live_YOUR_KEY",
        "Content-Type":  "application/json",
    },
    json={
        "sender_id": "YourBrand",
        "message":   "Hello! Your order has shipped.",
        "to":        ["233201234567"],
    }
)
print(res.json())
javascript — node.js (fetch)
const res = await fetch('https://bulkiemsg.com/api/v1/sms/send', {
  method:  'POST',
  headers: {
    'Authorization': 'Bearer bm_live_YOUR_KEY',
    'Content-Type':  'application/json',
  },
  body: JSON.stringify({
    sender_id: 'YourBrand',
    message:   'Hello! Your order has shipped.',
    to:        ['233201234567'],
  }),
});
console.log(await res.json());
javascript — browser (fetch)
// Works in any browser environment
async function sendSms(to, message) {
  const res = await fetch('https://bulkiemsg.com/api/v1/sms/send', {
    method:  'POST',
    headers: {
      'Authorization': 'Bearer bm_live_YOUR_KEY',
      'Content-Type':  'application/json',
    },
    body: JSON.stringify({
      sender_id: 'YourBrand',
      message,
      to: Array.isArray(to) ? to : [to],
    }),
  });

  const data = await res.json();

  if (!data.success) {
    throw new Error(data.error || 'SMS send failed');
  }

  return data;
}

// Usage
sendSms('233201234567', 'Hello! Your order has shipped.')
  .then(d => console.log(d.message))
  .catch(e => console.error(e.message));

Send SMS SMS

POST /api/v1/sms/send Send single or bulk SMS

Send an SMS to one recipient or thousands. Pass a single phone number or an array. Credits are deducted immediately — 1 credit per SMS page per recipient.

Request Parameters

ParameterTypeDescription
sender_idstringrequiredYour approved Sender ID (e.g. MyBrand). Must be approved in your dashboard first.
messagestringrequiredThe SMS body. 160 chars = 1 credit. Messages over 160 chars are split into pages (153 chars each). Unicode (emoji/Arabic) = 70 chars per page.
tostring | arrayrequiredA phone number or array of phone numbers. Accepts 233XXXXXXXXX (E.164) or local 0XXXXXXXXX format — both are normalised automatically.
bash — single recipient
curl -X POST https://bulkiemsg.com/api/v1/sms/send \
  -H "Authorization: Bearer bm_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sender_id": "MyBrand",
    "message":   "Your OTP is 482910. Valid for 5 minutes.",
    "to":        "233201234567"
  }'

# Bulk — pass an array
curl -X POST https://bulkiemsg.com/api/v1/sms/send \
  -H "Authorization: Bearer bm_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sender_id": "MyBrand",
    "message":   "Flash sale — 30% off today only!",
    "to":        ["233201234567", "233271234567", "0551234567"]
  }'
php
$payload = [
    'sender_id' => 'MyBrand',
    'message'   => 'Flash sale — 30% off today only!',
    'to'        => ['233201234567', '233271234567'],
];
$ch = curl_init('https://bulkiemsg.com/api/v1/sms/send');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POSTFIELDS     => json_encode($payload),
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer bm_live_YOUR_KEY',
        'Content-Type: application/json',
    ],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
python
import requests

r = requests.post(
    "https://bulkiemsg.com/api/v1/sms/send",
    headers={"Authorization": "Bearer bm_live_YOUR_KEY"},
    json={
        "sender_id": "MyBrand",
        "message":   "Flash sale — 30% off today only!",
        "to":        ["233201234567", "233271234567"],
    }
)
print(r.json())
javascript — node.js (fetch)
const r = await fetch('https://bulkiemsg.com/api/v1/sms/send', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer bm_live_YOUR_KEY',
    'Content-Type':  'application/json',
  },
  body: JSON.stringify({
    sender_id: 'MyBrand',
    message:   'Flash sale — 30% off today only!',
    to:        ['233201234567', '233271234567'],
  }),
});
console.log(await r.json());
javascript — browser (fetch + error handling)
async function sendBulkSms(recipients, message, senderId) {
  const res = await fetch('https://bulkiemsg.com/api/v1/sms/send', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer bm_live_YOUR_KEY',
      'Content-Type':  'application/json',
    },
    body: JSON.stringify({
      sender_id: senderId,
      message,
      to: Array.isArray(recipients) ? recipients : [recipients],
    }),
  });

  if (!res.ok && res.status !== 402) {
    throw new Error(`HTTP error: ${res.status}`);
  }

  const data = await res.json();

  if (!data.success) {
    throw new Error(data.error || 'Send failed');
  }

  return data;
}

// Usage
try {
  const result = await sendBulkSms(
    ['233201234567', '233271234567'],
    'Flash sale — 30% off today only!',
    'MyBrand'
  );
  console.log(result.message); // "Successfully sent to 2 recipient(s)."
} catch (e) {
  console.error('SMS error:', e.message);
}

Responses

200 OKSent successfully
success
{
  "success": true,
  "message": "Successfully sent to 3 recipient(s)."
}
402Insufficient credits
error
{
  "success": false,
  "error":   "Insufficient credits. Need 5, have 2."
}
401Unauthorized
error
{
  "success": false,
  "error":   "Invalid or revoked API key."
}

Check Balance SMS

GET /api/v1/sms/balance Get SMS credit balance

Returns the current SMS credit balance for the authenticated account. No request body required.

bash
curl https://bulkiemsg.com/api/v1/sms/balance \
  -H "Authorization: Bearer bm_live_YOUR_KEY"
php
$ch = curl_init('https://bulkiemsg.com/api/v1/sms/balance');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer bm_live_YOUR_KEY'],
]);
$res = json_decode(curl_exec($ch), true);
python
import requests
r = requests.get(
    "https://bulkiemsg.com/api/v1/sms/balance",
    headers={"Authorization": "Bearer bm_live_YOUR_KEY"}
)
print(r.json())
javascript — node.js
const r = await fetch('https://bulkiemsg.com/api/v1/sms/balance', {
  headers: { 'Authorization': 'Bearer bm_live_YOUR_KEY' }
});
console.log(await r.json());
javascript — browser
async function getBalance() {
  const res = await fetch('https://bulkiemsg.com/api/v1/sms/balance', {
    headers: { 'Authorization': 'Bearer bm_live_YOUR_KEY' }
  });
  const data = await res.json();
  if (!data.success) throw new Error(data.error);
  return data.sms_credits;
}

// Usage
getBalance()
  .then(credits => console.log(`Balance: ${credits} credits`))
  .catch(e => console.error(e.message));
200 OK
response
{
  "success":     true,
  "sms_credits": 500
}

Sender IDs SMS

All SMS must be sent with an approved Sender ID. Request one below — approval typically takes up to 48 hours.

POST /api/v1/sms/sender_ids Request new Sender ID

Submit a new Sender ID for approval. IDs must be 3–11 alphanumeric characters with no spaces.

Request Parameters

ParameterTypeDescription
sender_idstringrequiredThe Sender ID to request, e.g. MyBrand. 3–11 characters, no spaces.
bash
curl -X POST https://bulkiemsg.com/api/v1/sms/sender_ids \
  -H "Authorization: Bearer bm_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "sender_id": "MyBrand" }'
201 Created
response
{
  "success":      true,
  "message":      "Sender ID submitted for review.",
  "sender_id_id": 42
}
GET /api/v1/sms/sender_ids List Sender IDs

Returns all your Sender IDs and their current approval status (pending, approved, rejected).

bash
curl https://bulkiemsg.com/api/v1/sms/sender_ids \
  -H "Authorization: Bearer bm_live_YOUR_KEY"
200 OK
response
{
  "success": true,
  "sender_ids": [
    {
      "id":         42,
      "sender_id":  "MyBrand",
      "status":     "approved",
      "created_at": "2026-06-01 10:00:00"
    }
  ]
}

Send WhatsApp Message WhatsApp

ℹ️ WhatsApp messages are sent through your linked device. You must connect a device first — see Link Device.
POST /api/v1/whatsapp/send Send WhatsApp message

Sends a plain text WhatsApp message to one or more recipients via your connected device. Costs 1 credit per recipient.

Request Parameters

ParameterTypeDescription
tostring | arrayrequiredPhone number(s) in international format — 233XXXXXXXXX or local 0XXXXXXXXX.
messagestringrequiredThe message text. Max 4096 characters. Supports line breaks.
bash
curl -X POST https://bulkiemsg.com/api/v1/whatsapp/send \
  -H "Authorization: Bearer bm_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to":      "233201234567",
    "message": "Hello! Your appointment is confirmed for tomorrow at 10am."
  }'
200 OK
response
{
  "success": true,
  "message": "Message sent to 1 recipient(s)."
}

Link Device WhatsApp

POST /api/v1/whatsapp/session Get QR code for device link

Initiates a WhatsApp session and returns a QR code you can scan with your phone to link it. The session stays active until you unlink.

⚠️ Each account can only have one active WhatsApp session. Calling this again will reset the existing session.
bash
curl -X POST https://bulkiemsg.com/api/v1/whatsapp/session \
  -H "Authorization: Bearer bm_live_YOUR_KEY"
200 OK
response
{
  "success":  true,
  "qr_code":  "data:image/png;base64,iVBOR...",
  "message":  "Scan the QR code with WhatsApp on your phone.",
  "expires_in": 60
}

Display the qr_code base64 image to the user. The code expires in 60 seconds — call this endpoint again if it expires before scanning.

Rate Limits

The API enforces a limit of 60 requests per minute per API key. If you exceed this, you'll receive a 429 Too Many Requests response. Wait 60 seconds and retry.

Bulk SMS campaigns count as a single request regardless of recipient count — so sending to 10,000 numbers at once uses just 1 of your 60 requests.
429 response
{
  "success":    false,
  "error":      "Rate limit exceeded. Try again in 60 seconds.",
  "retry_after": 60
}

Errors & Codes

All errors return a JSON body with "success": false and an error string describing the problem. Use the HTTP status code to categorise the failure.

HTTP CodeMeaningCommon cause
200OKRequest succeeded.
400Bad RequestMissing or invalid parameter — check error for details.
401UnauthorizedAPI key missing, invalid, or revoked.
402Payment RequiredNot enough SMS credits to complete the request.
404Not FoundThe requested resource doesn't exist.
405Method Not AllowedWrong HTTP verb — check GET vs POST.
422UnprocessableValidation failed — e.g. invalid phone number format.
500Server ErrorInternal error. Contact support if this persists.
502Gateway ErrorSMS gateway unreachable. Credits not deducted. Retry shortly.

Common error messages

examples
// Missing API key
{ "success": false, "error": "API key is required." }

// Invalid key
{ "success": false, "error": "Invalid or revoked API key." }

// Not enough credits
{ "success": false, "error": "Insufficient credits. Need 10, have 3." }

// Sender ID not approved
{ "success": false, "error": "Sender ID 'MyBrand' is not approved." }

// No valid recipients
{ "success": false, "error": "No valid recipients provided." }