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.
https://your-domain.com/api/v2What'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).
/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.
| Parameter | Type | Required | Description |
|---|---|---|---|
| messages:send | scope | Optional | POST /sms/send, /sms/estimate |
| messages:read | scope | Optional | GET /sms/history, /sms/status/{id}, /sms/status/{id}/recipients |
| contacts:read | scope | Optional | GET /contacts, /contacts/{id} |
| contacts:write | scope | Optional | POST/PATCH /contacts |
| contacts:delete | scope | Optional | DELETE /contacts/{id} |
| contact-groups:read | scope | Optional | GET /contacts/groups, /contacts/groups/{id} |
| contact-groups:write | scope | Optional | POST/PATCH/DELETE /contacts/groups |
| templates:read | scope | Optional | GET /templates, /templates/{id} |
| templates:write | scope | Optional | POST/PATCH/DELETE /templates |
| sender-ids:read | scope | Optional | GET /sender-ids |
| sender-ids:request | scope | Optional | POST /sender-ids |
| account:read | scope | Optional | GET /balance |
| account:transactions:read | scope | Optional | GET /transactions |
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.
{
"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.
{
"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.
{
"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.
| Parameter | Type | Required | Description |
|---|---|---|---|
| UNAUTHENTICATED | 401 | Optional | Missing or invalid API key |
| PERMISSION_DENIED | 403 | Optional | API key lacks the required scope |
| INVALID_REQUEST | 400 | Optional | Malformed JSON, missing field, bad value |
| NOT_FOUND | 404 | Optional | Resource does not exist |
| INSUFFICIENT_CREDITS | 402 | Optional | Not enough credits to complete the send |
| INVALID_SENDER_ID | 400 | Optional | Sender ID is not approved on this account |
| RATE_LIMITED | 429 | Optional | Too many requests — back off and retry |
| IDEMPOTENCY_CONFLICT | 409 | Optional | Same Idempotency-Key reused with a different body |
| CONTENT_HELD_FOR_REVIEW | 422 | Optional | Message flagged by content screening; awaiting moderation |
| PROVIDER_ERROR | 502 | Optional | Upstream SMS provider rejected the request |
| INTERNAL_ERROR | 500 | Optional | Unexpected 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.
# 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'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.
Idempotency-Key: 7f3c9f88-2e1d-4a2c-9c1e-9b21d4aa55ffIDEMPOTENCY_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.
/api/v2/sms/sendHeaders
| Parameter | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Required | Bearer bms_live_… (or X-API-Key) |
| Idempotency-Key | string | Required | Unique UUID per logical send (replays cached for 24h) |
Request Body
phones, groupIds, contactIds, or sendToAllContacts. Sources can be combined; duplicates are removed.| Parameter | Type | Required | Description |
|---|---|---|---|
| message | string | Required | SMS content (max 918 chars for multi-part) |
| phones | string[] | Optional | Explicit recipient phone numbers |
| groupIds | string[] | Optional | Send to all contacts in these groups |
| contactIds | string[] | Optional | Send to specific contacts by ID |
| sendToAllContacts | boolean | Optional | Send to your entire contact list |
| senderId | string | Optional | Approved sender ID; defaults to first approved |
| scheduledAt | string | Optional | ISO 8601 datetime to schedule the send |
Example Request
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)
{
"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.
/api/v2/sms/passRequest Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| phone | string | Required | Recipient number (Ghana: 0XXXXXXXXX or 233XXXXXXXXX). Also accepted as to or recipient. |
| pass | string | number | Required | 3–16 alphanumeric characters (letters, digits, _ . -). Also accepted as otp or code. |
| senderId | string | Optional | Approved sender ID. Defaults to your account default. |
Example Request
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)
{
"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.
/api/v2/sms/estimateRequest Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| message | string | Required | Message text used to compute SMS parts |
| phones | string[] | Optional | Explicit recipient list (overrides recipientCount) |
| recipientCount | number | Optional | Use when you only know the count, not the numbers |
Example Request
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
{
"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.
/api/v2/balanceExample Request
curl 'https://your-domain.com/api/v2/balance' \
-H 'Authorization: Bearer bms_live_your_api_key'Response
{
"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.
/api/v2/sms/historyQuery Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| limit | number | Optional | 1–100, default 50 |
| cursor | string | Optional | Opaque cursor from previous response |
| status | string | Optional | PENDING | SENT | FAILED | HELD … |
Example Request
curl 'https://your-domain.com/api/v2/sms/history?limit=20&status=SENT' \
-H 'Authorization: Bearer bms_live_your_api_key'Response
{
"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.
/api/v2/sms/status/{messageId}Example Request
curl 'https://your-domain.com/api/v2/sms/status/msg_01HV89RAJ...' \
-H 'Authorization: Bearer bms_live_your_api_key'Response
{
"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.
/api/v2/sms/status/{messageId}/recipientsQuery Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| limit | number | Optional | 1–1000, default 100 |
| offset | number | Optional | Skip the first N recipients (default 0) |
Response
{
"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.
/api/v2/contacts/api/v2/contacts/api/v2/contacts/{id}/api/v2/contacts/{id}/api/v2/contacts/{id}List Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| limit | number | Optional | 1–100, default 50 |
| cursor | string | Optional | Opaque cursor from previous response |
| search | string | Optional | Match against name, phone, or email |
Create / Update Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| phone | string | Required | Required on POST. Auto-normalised to 233XXXXXXXXX |
| firstName | string | Optional | Contact first name |
| lastName | string | Optional | Contact last name |
| string | Optional | Contact email address |
Examples
# 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.
/api/v2/contacts/groups/api/v2/contacts/groups/api/v2/contacts/groups/{id}/api/v2/contacts/groups/{id}/api/v2/contacts/groups/{id}Create / Update Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Required | Required on POST. Group display name |
| description | string | Optional | Free-text description |
Examples
# 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).
/api/v2/sender-ids/api/v2/sender-idsRequest Body (POST)
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Required | Sender ID name (≤ 11 chars, uppercased) |
| purpose | string | Optional | Brief description for the approval team |
Examples
# 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.
/api/v2/templates/api/v2/templates/api/v2/templates/{id}/api/v2/templates/{id}/api/v2/templates/{id}Create / Update Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Required | Required on POST. Template label |
| body | string | Required | Required on POST. Template message text |
Examples
# 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.
/api/v2/transactionsQuery Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| limit | number | Optional | 1–100, default 50 |
| cursor | string | Optional | Opaque cursor from previous response |
| type | string | Optional | PURCHASE | ADJUSTMENT | EXPIRY | REFUND |
Example Request
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
/api/v2/sms/sendcurl -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
/api/v2/sms/status/{messageId}curl 'https://your-domain.com/api/v2/sms/status/msg_01HV89RAJ...' \
-H 'Authorization: Bearer bms_live_your_api_key'3. Page through history
/api/v2/sms/historylet 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);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.In your assistant, add a connector at:
https://your-domain.com/api/mcp - 2.Your browser opens this site and asks you to sign in.
- 3.Review exactly what the assistant can do, approve, and you are connected.
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.
| Package | Install | Registry |
|---|---|---|
| TypeScript | npm install @flashsms/sdk | |
| Python | pip install flashsms | |
| PHP | composer require flashsms/sdk | |
| WordPress | Download plugin zip |
/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.
npm install @flashsms/sdkimport { 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.
pip install flashsmsimport 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.
composer require flashsms/sdk<?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.Create a v2 API key in Developer → Keys.
- 2.Download the plugin zip and install it in WordPress (Plugins → Add New → Upload).
- 3.Settings → FlashSMS: paste the API key and an approved sender ID.
- 4.Use Test connection (no SMS), then Test send (1 live credit) to your phone.
SDKs · Raw HTTP examples
Copy-paste starters without an official package. These use Bearer auth, phones, and an Idempotency-Key on send.
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
https://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.
Authorization: Bearer ent_live_your_enterprise_key
# or
X-API-Key: ent_live_your_enterprise_keyEnterprise · Endpoints
POST /sms/send
Permission: sms:send
/api/enterprise/sms/sendcurl -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.
/api/enterprise/usagecurl 'https://your-domain.com/api/enterprise/usage' \
-H 'X-API-Key: ent_live_your_enterprise_key'Other routes
GET /balance—balance:readGET /invoices/client—invoice:readGET /analytics/client—analytics:readGET /webhooks—webhook:manage
Errors
400invalid payload ·401bad key ·403missing permission ·429rate limited
Ready to Get Started?
Create your account, generate an API key, and send your first SMS in minutes.