SMS Push API
Send SMS to any Ghana mobile number from your own system, using the units in your SMS Push wallet.
Base URL and authentication
https://YOUR-PROJECT-REF.supabase.co/functions/v1/api
Create a key in your dashboard under Developer API. Send it with every request in the X-API-Key header (or as Authorization: Bearer YOUR_KEY). Keep it secret — only use it from your server, never inside a website or mobile app that customers download.
Send SMS
POST /send
Same message to many numbers
{
"sender_id": "KOFIMART",
"message": "Your order is ready for pickup.",
"recipients": ["0241234567", "0201234567", "233551234567"]
}
Different message per number
{
"sender_id": "KOFIMART",
"messages": [
{ "recipient": "0241234567", "message": "Hi Ama, your code is 4821", "ref": "order-1001" },
{ "recipient": "0201234567", "message": "Hi Kojo, your code is 7730", "ref": "order-1002" }
]
}
| Field | Required | Description |
|---|---|---|
sender_id | Yes | An approved sender ID on your account. |
message + recipients | One of the two forms | Recipients can be an array or a comma-separated string. Up to 10,000 per request. |
messages | One of the two forms | Array of {recipient, message, ref}. ref is your own optional reference (max 100 characters). |
Numbers may be written as 0241234567, 241234567, 233241234567 or +233 24 123 4567. Duplicate numbers with the same message are sent once.
Response
{
"status": "success", // success | partial | failed
"campaign_id": "6c1f…",
"sender_id": "KOFIMART",
"accepted": 2,
"failed_to_submit": 0,
"invalid_numbers": [],
"duplicates_removed": 0,
"units_charged": 2,
"units_refunded": 0,
"balance": 9998,
"messages": [
{ "recipient": "233241234567", "ref": "spm1x9…", "client_ref": "order-1001", "units": 1, "status": "submitted" }
]
}
Check delivery
POST /status with {"refs": ["spm1x9…", "order-1001"]} — up to 500 refs. You can use our ref or your own client_ref. For one message: GET /status?ref=spm1x9…
{
"status": "success",
"data": [
{ "ref": "spm1x9…", "client_ref": "order-1001", "recipient": "233241234567", "sender_id": "KOFIMART",
"units": 1, "status": "delivered", "error": null, "created_at": "…", "updated_at": "…" }
]
}
| Status | Meaning |
|---|---|
queued | Received, about to be sent. |
submitted | Accepted by the network, waiting for the phone to receive it. |
delivered | Delivered to the phone. |
failed, rejected, expired | Not delivered. The units are refunded to your wallet. |
unknown | No final report from the network after 3 days. |
Check balance
GET /balance
{ "status": "success", "units": 9998 }
List sender IDs
GET /sender-ids
{ "status": "success", "data": [ { "sender_id": "KOFIMART", "status": "approved", "created_at": "…", "decided_at": "…" } ] }
Delivery callbacks
Set a callback URL (https) under Developer API in your dashboard. When messages reach a final status we send a POST to it, in batches of up to 500:
{
"event": "delivery_report",
"data": [
{ "ref": "spm1x9…", "client_ref": "order-1001", "recipient": "233241234567", "sender_id": "KOFIMART",
"units": 1, "status": "delivered", "error": null, "updated_at": "…" }
]
}
Reply with any 2xx status. If your server does not answer, we try again on the next cycle (every 2 minutes).
How units are counted
- Normal text: 1 unit for up to 160 characters. Longer messages use 153 characters per unit (161–306 characters = 2 units).
- If the message has emojis or special characters (for example curly quotes ’ “ or other alphabets): 1 unit for up to 70 characters, then 67 per unit.
- The characters
^ { } \ [ ] ~ | €count as 2 characters each. - Maximum message length is 1,530 characters.
Errors
{ "status": "error", "code": "INSUFFICIENT_BALANCE", "message": "Not enough units…" }
| HTTP | Code | Meaning |
|---|---|---|
| 401 | AUTH | Missing, wrong or revoked API key. |
| 403 | ACCOUNT_NOT_APPROVED | Your account is pending, rejected or suspended. |
| 400 | SENDER_NOT_APPROVED | The sender ID is not approved on your account. |
| 400 | VALIDATION / NO_VALID_NUMBERS | Something in the request is missing or invalid. |
| 402 | INSUFFICIENT_BALANCE | Not enough units in your wallet. Nothing was sent. |
| 502 | — | The network did not accept the messages. Units were refunded. |
Code examples
PHP
$ch = curl_init("BASE_URL/send");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["X-API-Key: YOUR_KEY", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode([
"sender_id" => "KOFIMART",
"message" => "Your order is ready",
"recipients" => ["0241234567"],
]),
]);
$result = json_decode(curl_exec($ch), true);
JavaScript (Node.js)
const res = await fetch("BASE_URL/send", {
method: "POST",
headers: { "X-API-Key": process.env.SMSPUSH_KEY, "Content-Type": "application/json" },
body: JSON.stringify({ sender_id: "KOFIMART", message: "Your order is ready", recipients: ["0241234567"] }),
});
const result = await res.json();
Python
import requests
r = requests.post("BASE_URL/send",
headers={"X-API-Key": "YOUR_KEY"},
json={"sender_id": "KOFIMART", "message": "Your order is ready", "recipients": ["0241234567"]})
print(r.json())