FlashSMS

Developer docs

Documentation

REST API v2, MCP for AI assistants, SDK examples, and Enterprise API — all in one place.

v2 · Overview

v2 is a forward-looking REST surface with stable response envelopes, cursor pagination, idempotent sends, scoped permissions, and a versioned contract. v1 will be retired on 1 July 2026 — pick v2 for new integrations and plan your migration before then.

Base URLhttps://your-domain.com/api/v2

What's new vs v1

  • Every response wrapped in { data, meta } or { error, meta } — no more shape drift between endpoints.
  • Cursor-based pagination on all list endpoints (replaces page/limit).
  • Required Idempotency-Key on POST /sms/send — safe to retry.
  • Typed error codes (UNAUTHENTICATED, INVALID_REQUEST, ...) decoupled from HTTP status.
  • Scope-based permissions (messages:send, contacts:read, ...) granted to keys created with version v2.
  • apiVersion + requestId on every response for support and migrations.
  • Sends return 202 Accepted — large campaigns are queued, not blocked on the request.

Authentication

Same header format as v1 — use Authorization: Bearer (or X-API-Key). v2 additionally checks a per-endpoint scope (see below).

v2 endpoints require a v2 key
Keys are version-locked. A v1 key sent to /api/v2/* returns 403 PERMISSION_DENIED with { keyVersion: "v1", requiredVersion: "v2" } in the error details. Generate a v2 key from the dashboard — pick v2 in the version selector when creating it. v1 keys continue to work on /api/v1/*.

v2 · Scopes

Each v2 endpoint requires the API key to carry a specific scope. Scopes let you mint narrow keys for specific integrations.

ParameterTypeRequiredDescription
messages:sendscopeOptionalPOST /sms/send, /sms/estimate
messages:readscopeOptionalGET /sms/history, /sms/status/{id}, /sms/status/{id}/recipients
contacts:readscopeOptionalGET /contacts, /contacts/{id}
contacts:writescopeOptionalPOST/PATCH /contacts
contacts:deletescopeOptionalDELETE /contacts/{id}
contact-groups:readscopeOptionalGET /contacts/groups, /contacts/groups/{id}
contact-groups:writescopeOptionalPOST/PATCH/DELETE /contacts/groups
templates:readscopeOptionalGET /templates, /templates/{id}
templates:writescopeOptionalPOST/PATCH/DELETE /templates
sender-ids:readscopeOptionalGET /sender-ids
sender-ids:requestscopeOptionalPOST /sender-ids
account:readscopeOptionalGET /balance
account:transactions:readscopeOptionalGET /transactions
Scopes are checked on v2 keys only
Scope enforcement runs after the version check — only keys created with version v2 reach this stage. v1 keys are rejected at the version check before any scope is evaluated. When generating a v2 key, grant only the scopes the integration needs; missing a scope returns 403 PERMISSION_DENIED with the required scope name in error.details.

v2 · Envelopes

v2 wraps every response in a stable envelope. meta.requestId echoes back on every call — quote it when contacting support.

Success envelope

Single-resource responses carry the resource under data.

json
{
  "data": {
    "id": "msg_01HV...",
    "status": "PENDING",
    "recipientCount": 3,
    "creditsUsed": 3,
    "remainingCredits": 1247,
    "senderId": "MyBrand",
    "scheduledAt": null,
    "createdAt": "2025-04-25T14:31:09.812Z"
  },
  "meta": {
    "requestId": "8c2d…",
    "apiVersion": "2025-04-25"
  }
}

List envelope

List endpoints return an array under data plus a pagination object.

json
{
  "data": [ /* items */ ],
  "pagination": {
    "nextCursor": "MDFIVjg5UkFK...",
    "hasMore": true,
    "limit": 50
  },
  "meta": { "requestId": "…", "apiVersion": "2025-04-25" }
}

Error envelope

Failures carry a typed code under error.code, a human-readable message, and optional details.

json
{
  "error": {
    "code": "INSUFFICIENT_CREDITS",
    "message": "Account does not have enough SMS credits",
    "details": { "required": 250, "available": 127 }
  },
  "meta": { "requestId": "…", "apiVersion": "2025-04-25" }
}

v2 · Error Codes

Error codes are stable and decoupled from HTTP status — branch on error.code, not the status line.

ParameterTypeRequiredDescription
UNAUTHENTICATED401OptionalMissing or invalid API key
PERMISSION_DENIED403OptionalAPI key lacks the required scope
INVALID_REQUEST400OptionalMalformed JSON, missing field, bad value
NOT_FOUND404OptionalResource does not exist
INSUFFICIENT_CREDITS402OptionalNot enough credits to complete the send
INVALID_SENDER_ID400OptionalSender ID is not approved on this account
RATE_LIMITED429OptionalToo many requests — back off and retry
IDEMPOTENCY_CONFLICT409OptionalSame Idempotency-Key reused with a different body
CONTENT_HELD_FOR_REVIEW422OptionalMessage flagged by content screening; awaiting moderation
PROVIDER_ERROR502OptionalUpstream SMS provider rejected the request
INTERNAL_ERROR500OptionalUnexpected server error — safe to retry

v2 · Pagination

List endpoints use opaque cursors. Pass limit (1–100, default 50) and the cursor from the previous response. Stop when hasMore is false.

bash
# Page 1
curl 'https://your-domain.com/api/v2/sms/history?limit=50' \
  -H 'Authorization: Bearer bms_live_your_api_key'

# Page 2 — pass nextCursor from the previous response
curl 'https://your-domain.com/api/v2/sms/history?limit=50&cursor=MDFIVjg5UkFK...' \
  -H 'Authorization: Bearer bms_live_your_api_key'
Per-recipient lists use offset
GET /sms/status/{id}/recipients uses limit+offset instead of cursors, since recipient order is fixed at send time.

v2 · Idempotency

Every POST endpoint that creates a resource (/sms/send, /contacts, /contacts/groups, /sender-ids, /templates) requires an Idempotency-Key header.

Replays of the same key within 24 hours return the original response — safe to retry on network errors. Use a fresh UUID per logical operation.

http
Idempotency-Key: 7f3c9f88-2e1d-4a2c-9c1e-9b21d4aa55ff
Reusing a key with a different body
If you send the same key with a different request body, v2 returns IDEMPOTENCY_CONFLICT (409) rather than executing it twice.

v2 · Send SMS

Send to phone numbers, contact IDs, group IDs, or your entire contact list. Returns 202 Accepted — large campaigns are queued, not blocked on the request.

POST/api/v2/sms/send

Headers

ParameterTypeRequiredDescription
AuthorizationstringRequiredBearer bms_live_… (or X-API-Key)
Idempotency-KeystringRequiredUnique UUID per logical send (replays cached for 24h)

Request Body

Recipient sources
Provide at least one of: phones, groupIds, contactIds, or sendToAllContacts. Sources can be combined; duplicates are removed.
ParameterTypeRequiredDescription
messagestringRequiredSMS content (max 918 chars for multi-part)
phonesstring[]OptionalExplicit recipient phone numbers
groupIdsstring[]OptionalSend to all contacts in these groups
contactIdsstring[]OptionalSend to specific contacts by ID
sendToAllContactsbooleanOptionalSend to your entire contact list
senderIdstringOptionalApproved sender ID; defaults to first approved
scheduledAtstringOptionalISO 8601 datetime to schedule the send

Example Request

bash
curl -X POST 'https://your-domain.com/api/v2/sms/send' \
  -H 'Authorization: Bearer bms_live_your_api_key' \
  -H 'Idempotency-Key: 7f3c9f88-2e1d-4a2c-9c1e-9b21d4aa55ff' \
  -H 'Content-Type: application/json' \
  -d '{
    "message": "Hello from FlashSMS Africa!",
    "phones": ["0201234567", "0241234567"],
    "senderId": "MyBrand"
  }'

Response (202)

json
{
  "data": {
    "id": "msg_01HV89RAJ...",
    "status": "PENDING",
    "recipientCount": 2,
    "invalidRecipients": [],
    "creditsUsed": 2,
    "remainingCredits": 998,
    "senderId": "MyBrand",
    "scheduledAt": null,
    "createdAt": "2025-04-25T14:31:09.812Z"
  },
  "meta": { "requestId": "8c2d…", "apiVersion": "2025-04-25" }
}

v2 · Send Pass SMS

Send a single-recipient login pass message. The message body is fixed: {pass} is your login pass. Credits are reserved before the provider call and refunded automatically on failure. Requires the messages:send scope.

POST/api/v2/sms/pass

Request Body

ParameterTypeRequiredDescription
phonestringRequiredRecipient number (Ghana: 0XXXXXXXXX or 233XXXXXXXXX). Also accepted as to or recipient.
passstring | numberRequired3–16 alphanumeric characters (letters, digits, _ . -). Also accepted as otp or code.
senderIdstringOptionalApproved sender ID. Defaults to your account default.

Example Request

bash
curl -X POST 'https://your-domain.com/api/v2/sms/pass' \
  -H 'Authorization: Bearer bms_live_your_api_key' \
  -H 'Content-Type: application/json' \
  -d '{
    "phone": "0201234567",
    "pass": "847291",
    "senderId": "MyBrand"
  }'

Response (200)

json
{
  "data": {
    "id": "cmjveqxgf0001jr04abc123",
    "status": "SENT",
    "recipient": "233201234567",
    "creditsUsed": 1,
    "remainingCredits": 499,
    "senderId": "MyBrand",
    "provider": "MNOTIFY",
    "providerMessageId": "mnotify-abc-123",
    "createdAt": "2025-04-25T14:31:09.812Z"
  },
  "meta": { "requestId": "8c2d…", "apiVersion": "2025-04-25" }
}

v2 · Estimate Cost

Calculate the credit cost of a message before sending. No credits are deducted.

POST/api/v2/sms/estimate

Request Body

ParameterTypeRequiredDescription
messagestringRequiredMessage text used to compute SMS parts
phonesstring[]OptionalExplicit recipient list (overrides recipientCount)
recipientCountnumberOptionalUse when you only know the count, not the numbers

Example Request

bash
curl -X POST 'https://your-domain.com/api/v2/sms/estimate' \
  -H 'Authorization: Bearer bms_live_your_api_key' \
  -H 'Content-Type: application/json' \
  -d '{ "message": "Hello world", "recipientCount": 250 }'

Response

json
{
  "data": {
    "message": "Hello world",
    "partsPerMessage": 1,
    "recipientCount": 250,
    "creditsNeeded": 250,
    "currentBalance": 1247,
    "canAfford": true
  },
  "meta": { "requestId": "…", "apiVersion": "2025-04-25" }
}

v2 · Balance

Returns the authenticated account's expiring and non-expiring credit balances.

GET/api/v2/balance

Example Request

bash
curl 'https://your-domain.com/api/v2/balance' \
  -H 'Authorization: Bearer bms_live_your_api_key'

Response

json
{
  "data": {
    "expiry": {
      "credits": 1000,
      "expiresAt": "2025-05-25T00:00:00.000Z"
    },
    "nonExpiry": { "credits": 247 },
    "total": 1247
  },
  "meta": { "requestId": "…", "apiVersion": "2025-04-25" }
}

v2 · SMS History

List sent messages, newest first. Cursor-paginated.

GET/api/v2/sms/history

Query Parameters

ParameterTypeRequiredDescription
limitnumberOptional1–100, default 50
cursorstringOptionalOpaque cursor from previous response
statusstringOptionalPENDING | SENT | FAILED | HELD …

Example Request

bash
curl 'https://your-domain.com/api/v2/sms/history?limit=20&status=SENT' \
  -H 'Authorization: Bearer bms_live_your_api_key'

Response

json
{
  "data": [
    {
      "id": "msg_01HV89RAJ...",
      "message": "Hello from MyBrand!",
      "recipientCount": 2,
      "creditsUsed": 2,
      "status": "SENT",
      "senderId": "MyBrand",
      "scheduledAt": null,
      "sentAt": "2025-04-25T14:31:11.000Z",
      "createdAt": "2025-04-25T14:31:09.812Z"
    }
  ],
  "pagination": {
    "nextCursor": "MDFIVjg5UkFK...",
    "hasMore": true,
    "limit": 20
  },
  "meta": { "requestId": "…", "apiVersion": "2025-04-25" }
}

v2 · Message Status

Fetch a single message by ID.

GET/api/v2/sms/status/{messageId}

Example Request

bash
curl 'https://your-domain.com/api/v2/sms/status/msg_01HV89RAJ...' \
  -H 'Authorization: Bearer bms_live_your_api_key'

Response

json
{
  "data": {
    "id": "msg_01HV89RAJ...",
    "message": "Hello from MyBrand!",
    "recipientCount": 2,
    "creditsUsed": 2,
    "status": "SENT",
    "senderId": "MyBrand",
    "scheduledAt": null,
    "sentAt": "2025-04-25T14:31:11.000Z",
    "createdAt": "2025-04-25T14:31:09.812Z"
  },
  "meta": { "requestId": "…", "apiVersion": "2025-04-25" }
}

v2 · Delivery Report

Per-recipient delivery status with rolled-up stats.

GET/api/v2/sms/status/{messageId}/recipients

Query Parameters

ParameterTypeRequiredDescription
limitnumberOptional1–1000, default 100
offsetnumberOptionalSkip the first N recipients (default 0)

Response

json
{
  "data": {
    "messageId": "msg_01HV89RAJ...",
    "status": "SENT",
    "recipientCount": 2,
    "stats": {
      "delivered": 2,
      "submitted": 0,
      "notDelivered": 0,
      "expired": 0,
      "failed": 0,
      "pending": 0,
      "deliveryRate": 100
    },
    "recipients": [
      { "phone": "233201234567", "status": "DELIVERED", "sentAt": "2025-04-25T14:31:11.000Z" }
    ],
    "pagination": { "total": 2, "limit": 100, "offset": 0, "hasMore": false, "nextOffset": null }
  },
  "meta": { "requestId": "…", "apiVersion": "2025-04-25" }
}

v2 · Contacts

Manage individual contacts. List/get use cursor pagination; create/update/delete are idempotent on POST.

GET/api/v2/contacts
POST/api/v2/contacts
GET/api/v2/contacts/{id}
PUT/api/v2/contacts/{id}
DELETE/api/v2/contacts/{id}

List Query Parameters

ParameterTypeRequiredDescription
limitnumberOptional1–100, default 50
cursorstringOptionalOpaque cursor from previous response
searchstringOptionalMatch against name, phone, or email

Create / Update Body

ParameterTypeRequiredDescription
phonestringRequiredRequired on POST. Auto-normalised to 233XXXXXXXXX
firstNamestringOptionalContact first name
lastNamestringOptionalContact last name
emailstringOptionalContact email address

Examples

bash
# List contacts
curl 'https://your-domain.com/api/v2/contacts?limit=50&search=ama' \
  -H 'Authorization: Bearer bms_live_your_api_key'

# Create a contact
curl -X POST 'https://your-domain.com/api/v2/contacts' \
  -H 'Authorization: Bearer bms_live_your_api_key' \
  -H 'Idempotency-Key: 9c5e…' \
  -H 'Content-Type: application/json' \
  -d '{ "phone": "0201234567", "firstName": "Ama", "lastName": "Mensah" }'

# Update a contact (PATCH)
curl -X PATCH 'https://your-domain.com/api/v2/contacts/ctc_01HV...' \
  -H 'Authorization: Bearer bms_live_your_api_key' \
  -H 'Content-Type: application/json' \
  -d '{ "email": "[email protected]" }'

# Delete (soft-delete)
curl -X DELETE 'https://your-domain.com/api/v2/contacts/ctc_01HV...' \
  -H 'Authorization: Bearer bms_live_your_api_key'

v2 · Contact Groups

Group contacts for targeted sends. Deleting a group does not delete its contacts.

GET/api/v2/contacts/groups
POST/api/v2/contacts/groups
GET/api/v2/contacts/groups/{id}
PUT/api/v2/contacts/groups/{id}
DELETE/api/v2/contacts/groups/{id}

Create / Update Body

ParameterTypeRequiredDescription
namestringRequiredRequired on POST. Group display name
descriptionstringOptionalFree-text description

Examples

bash
# List groups
curl 'https://your-domain.com/api/v2/contacts/groups' \
  -H 'Authorization: Bearer bms_live_your_api_key'

# Create a group
curl -X POST 'https://your-domain.com/api/v2/contacts/groups' \
  -H 'Authorization: Bearer bms_live_your_api_key' \
  -H 'Idempotency-Key: 9c5e…' \
  -H 'Content-Type: application/json' \
  -d '{ "name": "VIP Customers", "description": "High-value clients" }'

v2 · Sender IDs

List approved sender IDs or request a new one for approval (max 11 characters, uppercased).

GET/api/v2/sender-ids
POST/api/v2/sender-ids

Request Body (POST)

ParameterTypeRequiredDescription
namestringRequiredSender ID name (≤ 11 chars, uppercased)
purposestringOptionalBrief description for the approval team

Examples

bash
# List sender IDs
curl 'https://your-domain.com/api/v2/sender-ids' \
  -H 'Authorization: Bearer bms_live_your_api_key'

# Request a new sender ID
curl -X POST 'https://your-domain.com/api/v2/sender-ids' \
  -H 'Authorization: Bearer bms_live_your_api_key' \
  -H 'Idempotency-Key: 9c5e…' \
  -H 'Content-Type: application/json' \
  -d '{ "name": "MyBrand", "purpose": "Customer notifications" }'

v2 · Templates

Reusable SMS message bodies.

GET/api/v2/templates
POST/api/v2/templates
GET/api/v2/templates/{id}
PUT/api/v2/templates/{id}
DELETE/api/v2/templates/{id}

Create / Update Body

ParameterTypeRequiredDescription
namestringRequiredRequired on POST. Template label
bodystringRequiredRequired on POST. Template message text

Examples

bash
# Create a template
curl -X POST 'https://your-domain.com/api/v2/templates' \
  -H 'Authorization: Bearer bms_live_your_api_key' \
  -H 'Idempotency-Key: 9c5e…' \
  -H 'Content-Type: application/json' \
  -d '{ "name": "OTP", "body": "Your code is {{code}}" }'

v2 · Transactions

Credit ledger — purchases, usage, refunds, expirations, and admin adjustments.

GET/api/v2/transactions

Query Parameters

ParameterTypeRequiredDescription
limitnumberOptional1–100, default 50
cursorstringOptionalOpaque cursor from previous response
typestringOptionalPURCHASE | ADJUSTMENT | EXPIRY | REFUND

Example Request

bash
curl 'https://your-domain.com/api/v2/transactions?limit=20&type=PURCHASE' \
  -H 'Authorization: Bearer bms_live_your_api_key'

v2 · Worked Example

A complete send-then-poll cycle showing the v2 envelope, idempotency, and cursor pagination.

1. Send a message

POST/api/v2/sms/send
bash
curl -X POST 'https://your-domain.com/api/v2/sms/send' \
  -H 'Authorization: Bearer bms_live_your_api_key' \
  -H 'Idempotency-Key: 7f3c9f88-2e1d-4a2c-9c1e-9b21d4aa55ff' \
  -H 'Content-Type: application/json' \
  -d '{
    "message": "Hello from FlashSMS Africa v2",
    "senderId": "MyBrand",
    "phones": ["0201234567"]
  }'

# 202 Accepted
{
  "data": {
    "id": "msg_01HV89RAJ...",
    "status": "PENDING",
    "recipientCount": 1,
    "invalidRecipients": [],
    "creditsUsed": 1,
    "remainingCredits": 1246,
    "senderId": "MyBrand",
    "scheduledAt": null,
    "createdAt": "2025-04-25T14:31:09.812Z"
  },
  "meta": { "requestId": "…", "apiVersion": "2025-04-25" }
}

2. Check delivery status

GET/api/v2/sms/status/{messageId}
bash
curl 'https://your-domain.com/api/v2/sms/status/msg_01HV89RAJ...' \
  -H 'Authorization: Bearer bms_live_your_api_key'

3. Page through history

GET/api/v2/sms/history
javascript
let cursor = null;
do {
  const url = new URL('https://your-domain.com/api/v2/sms/history');
  url.searchParams.set('limit', '50');
  if (cursor) url.searchParams.set('cursor', cursor);

  const res = await fetch(url, {
    headers: { Authorization: 'Bearer bms_live_your_api_key' },
  });
  const { data, pagination } = await res.json();

  for (const msg of data) {
    console.log(msg.id, msg.status, msg.sentAt);
  }
  cursor = pagination.nextCursor;
} while (cursor);
Migrating from v1?
Most field names carry over. Watch for: recipients phones on send, page/limit pagination → cursor/limit, error { error: "..." } { error: { code, message } }, and the new required Idempotency-Key header on send.

AI assistants

MCP

Connect Claude or another assistant to your account over the Model Context Protocol — no API keys in the chat.

MCP · Connect

Once connected, you can ask about credit balance, contacts, and delivery in plain language without opening the dashboard.

  1. 1.In your assistant, add a connector at:https://your-domain.com/api/mcp
  2. 2.Your browser opens this site and asks you to sign in.
  3. 3.Review exactly what the assistant can do, approve, and you are connected.
Your password stays here
The assistant receives a limited pass for what you approved. You can withdraw it any time from Connected apps.
How long a connection lasts
Access tokens expire after 1 hour; your assistant refreshes them automatically using a refresh token that lasts 90 days. If refresh fails (or you signed out everywhere), reconnect the MCP connector — you do not need a new API key.

MCP · What it can do

  • View your credit balanceSee how many SMS credits you have and when they expire.
  • View your transaction historySee credit purchases, adjustments, refunds, and expiries.
  • View your contactsRead your saved contacts and their phone numbers.
  • View your contact groupsRead your contact groups and how many people are in each.
  • View your message templatesRead your saved SMS templates.
  • View your sender IDsSee your sender IDs and whether they are approved.
  • View your sent messagesRead your message history and per-recipient delivery results.
  • Send SMS messages and spend creditsSend messages to your contacts and deduct credits from your balance. Also required to estimate what a send would cost.

Sending messages is the only permission that spends credits, and it is marked clearly on the approval screen. An assistant must confirm recipient count and cost before any send.

MCP · Manage access

Every connected app is listed under Connected apps, with when you connected it and when it was last used. Disconnecting takes effect immediately. Signing out of all devices also disconnects every app.

MCP · For developers

The endpoint implements MCP over Streamable HTTP with OAuth 2.1 and PKCE. Clients can register dynamically; discovery documents are at /.well-known/oauth-protected-resource and /.well-known/oauth-authorization-server. Access tokens last 1 hour (expires_in); refresh tokens last 90 days (refresh_token_expires_in) and rotate on each use. A v2 API key may be used instead of OAuth by sending it as a bearer token.

Libraries

Official SDKs & plugins

Install an official client or the WordPress plugin. All v2 clients require a bms_live_* API key.

SDKs · Overview

Create a v2 key in Developer → Keys. Use testConnection() or a balance request to verify the key without sending SMS.

PackageInstallRegistry
TypeScriptnpm install @flashsms/sdk
Pythonpip install flashsms
PHPcomposer require flashsms/sdk
WordPressDownload plugin zip
API v1
New v1 keys are no longer issued. Existing v1 keys continue to work on /api/v1 via REST. Official SDKs are v2 only.

SDKs · TypeScript

Official npm package for Node.js and browsers. Includes FlashsmsClient (prepaid v2) and EnterpriseClient.

bash
npm install @flashsms/sdk
typescript
import { FlashsmsClient } from '@flashsms/sdk';

const client = new FlashsmsClient({
  apiKey: process.env.FLASHSMS_API_KEY!, // bms_live_...
});

// No SMS sent
const { data: balance } = await client.testConnection();
console.log('Credits:', balance.total);

// Live SMS — charges credits
const { data: sent } = await client.sendMessage({
  message: 'Hello from FlashSMS',
  phones: ['0201234567'],
  senderId: 'YourBrand',
});

SDKs · Python

Requires Python 3.10+. Set FLASHSMS_API_KEY or pass the key to the constructor.

bash
pip install flashsms
python
import os
from flashsms import FlashsmsClient

client = FlashsmsClient(api_key=os.environ["FLASHSMS_API_KEY"])

# No SMS sent
balance = client.test_connection()
print("Credits:", balance["data"]["total"])

# Live SMS — charges credits
sent = client.send_message(
    message="Hello from FlashSMS",
    phones=["0201234567"],
    senderId="YourBrand",
)

SDKs · PHP

Requires PHP 8.1+ with ext-curl and ext-json.

bash
composer require flashsms/sdk
php
<?php

use Flashsms\FlashsmsClient;

$client = new FlashsmsClient(getenv('FLASHSMS_API_KEY'));

// No SMS sent
$balance = $client->testConnection();
echo 'Credits: ' . $balance['data']['total'] . PHP_EOL;

// Live SMS — charges credits
$sent = $client->sendMessage([
    'message' => 'Hello from FlashSMS',
    'phones' => ['0201234567'],
    'senderId' => 'YourBrand',
]);

SDKs · WordPress & WooCommerce

Send order notifications and marketing SMS from WordPress. Requires a v2 API key and an approved sender ID.

  1. 1.Create a v2 API key in Developer → Keys.
  2. 2.Download the plugin zip and install it in WordPress (Plugins → Add New → Upload).
  3. 3.Settings → FlashSMS: paste the API key and an approved sender ID.
  4. 4.Use Test connection (no SMS), then Test send (1 live credit) to your phone.
Live SMS
Test send delivers one real SMS and deducts credits. Test connection only checks your key and balance.

SDKs · Raw HTTP examples

Copy-paste starters without an official package. These use Bearer auth, phones, and an Idempotency-Key on send.

Node.js
const API_KEY = 'bms_live_your_api_key';
const BASE_URL = 'https://your-domain.com/api/v2';
const headers = {
  'Authorization': `Bearer ${API_KEY}`,
  'Content-Type': 'application/json',
  'Idempotency-Key': crypto.randomUUID(),
};

async function sendSms(phones, message, senderId = 'FlashSMS') {
  const res = await fetch(`${BASE_URL}/sms/send`, {
    method: 'POST',
    headers,
    body: JSON.stringify({ phones, message, senderId }),
  });
  return res.json();
}

async function checkBalance() {
  const res = await fetch(`${BASE_URL}/balance`, {
    headers: { Authorization: `Bearer ${API_KEY}` },
  });
  return res.json();
}

const result = await sendSms(['0201234567'], 'Hello from FlashSMS Africa!');
console.log(result.data);

const { data } = await checkBalance();
console.log(`Balance: ${data.balance} credits`);

Client integrations

Enterprise API

Bulk SMS for enterprise clients using admin-issued keys and fine-grained permissions.

Enterprise · Overview

Base URLhttps://your-domain.com/api/enterprise
  • All endpoints are relative to this base URL.
  • HTTPS only; requests without TLS are rejected.
  • Default rate limit: 5000 requests/min per API key (configurable).
  • Ghana numbers accepted as 0XXXXXXXXX or 233XXXXXXXXX.

Enterprise · Authentication

Use either header on every request. Keys are created by admins and scoped with permissions such as sms:send, sms:read, usage:read, and balance:read.

bash
Authorization: Bearer ent_live_your_enterprise_key
# or
X-API-Key: ent_live_your_enterprise_key
Server-side only
Do not expose enterprise keys in client-side code. Store them in environment variables.

Enterprise · Endpoints

POST /sms/send

Permission: sms:send

POST/api/enterprise/sms/send
bash
curl -X POST 'https://your-domain.com/api/enterprise/sms/send' \
  -H 'X-API-Key: ent_live_your_enterprise_key' \
  -H 'Content-Type: application/json' \
  -d '{
    "recipients": ["0201234567"],
    "message": "Hello from Enterprise API",
    "senderId": "MyBrand"
  }'

GET /usage

Permission: usage:read — current billing period totals.

GET/api/enterprise/usage
bash
curl 'https://your-domain.com/api/enterprise/usage' \
  -H 'X-API-Key: ent_live_your_enterprise_key'

Other routes

  • GET /balance balance:read
  • GET /invoices/client invoice:read
  • GET /analytics/client analytics:read
  • GET /webhooks webhook:manage

Errors

  • 400 invalid payload · 401 bad key · 403 missing permission · 429 rate limited

Ready to Get Started?

Create your account, generate an API key, and send your first SMS in minutes.