SimplySend API
Integrate SMS messaging directly into your system. Send messages, check your credit balance, and retrieve delivery reports — all through a simple REST API.
Authentication
Every request must include your API key in the X-API-Key header. Your key is issued by SimplySend when you sign up for API access.
X-API-Key: ss_live_your_api_key_here
All API keys start with ss_live_.
If you do not have a key yet, contact SimplySend on WhatsApp: 0543528772.
Base URL
All endpoints are relative to the following base URL:
All requests and responses use JSON.
Set Content-Type: application/json on every POST request.
Send SMS
Send a message to one recipient or a batch of up to 1,000 recipients in a single request. The recipient field accepts either a single phone number string or an array of numbers.
Headers
| Header | Value | |
|---|---|---|
| X-API-Key | string | Required |
| Content-Type | application/json | Required |
Body Parameters
| Parameter | Type | Description | |
|---|---|---|---|
| recipient | string | string[] | Required | A single phone number or an array of phone numbers. Numbers should be in Ghana format (e.g. 0244123456 or +233244123456). Maximum 1,000 numbers per request. |
| message | string | Required | The message text to send. Messages over 160 characters are sent as multi-part SMS and consume additional units accordingly. |
| sender | string | Required | Your registered Sender ID. This is what recipients see as the sender name. Must be pre-approved by SimplySend. |
Single Recipient Example
{
"recipient": "0244123456",
"message": "Dear Patient, your test results are ready for collection.",
"sender": "HospitalName"
}
Batch Example
{
"recipient": [
"0244123456",
"0201234567",
"0554321098"
],
"message": "Dear Patient, your appointment is tomorrow at 10:00am. Please arrive 15 minutes early.",
"sender": "HospitalName"
}
Success Response — 200
{
"success": true,
"campaign_id": "3f9a2b1c-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"recipients_count": 3,
"units_used": 3,
"pages_per_message": 1
}campaign_id returned in the response. You will need it to check delivery status via the Delivery Report endpoint.Personalized SMS
Use template variables in your message to personalize each SMS with the recipient's name. When template variables are detected, SimplySend sends each message individually with the correct name substituted in.
POST /api-send endpoint. You simply pass recipients as objects instead of plain strings, and include a {firstname} or {lastname} variable in your message.Supported Variables
| Variable | Replaced with |
|---|---|
| {firstname} | Recipient's first name |
| {lastname} | Recipient's last name |
Any unrecognized variables are silently removed from the message before sending.
Request Body
Pass recipient as an array of objects, each with a phone and optional firstname / lastname field.
{
"recipient": [
{ "phone": "0244123456", "firstname": "Kwame" },
{ "phone": "0201234567", "firstname": "Abena" },
{ "phone": "0554321098", "firstname": "Yaw" }
],
"message": "Dear {firstname}, your appointment is tomorrow at 10am. Please arrive 15 minutes early.",
"sender": "HospitalName"
}
What each recipient receives:
→ Kwame: "Dear Kwame, your appointment is tomorrow at 10am. Please arrive 15 minutes early." → Abena: "Dear Abena, your appointment is tomorrow at 10am. Please arrive 15 minutes early." → Yaw: "Dear Yaw, your appointment is tomorrow at 10am. Please arrive 15 minutes early."
Success Response — 200
{
"success": true,
"campaign_id": "3f9a2b1c-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"recipients_count": 3,
"units_used": 3,
"pages_per_message": 1
}All Three Recipient Formats
The same endpoint accepts any of these — SimplySend detects which format you are using automatically:
"recipient": "0244123456"
"recipient": ["0244123456", "0201234567"]
"recipient": [ { "phone": "0244123456", "firstname": "Kwame" }, { "phone": "0201234567", "firstname": "Abena" } ]
Check Balance
Returns the current SMS credit balance for your account. Use this to check available units before sending a large campaign.
Headers
| Header | Value | |
|---|---|---|
| X-API-Key | string | Required |
No request body required.
Success Response — 200
{
"success": true,
"balance": 24750,
"unit": "SMS units"
}Delivery Report
Retrieve the delivery status for a campaign. Pass the campaign_id returned from the Send SMS endpoint as a query parameter.
Note that delivery statuses update asynchronously — call this endpoint a few minutes after sending for the most complete picture.
Headers
| Header | Value | |
|---|---|---|
| X-API-Key | string | Required |
Query Parameters
| Parameter | Type | Description | |
|---|---|---|---|
| campaign_id | string (UUID) | Required | The campaign_id returned from the Send SMS response. |
Example Request URL
/api-report?campaign_id=3f9a2b1c-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Success Response — 200
{
"success": true,
"campaign_id": "3f9a2b1c-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"status": "completed",
"sender": "HospitalName",
"created_at": "2026-07-23T10:30:00.000Z",
"summary": {
"total": 3,
"delivered": 3,
"pending": 0,
"failed": 0
}
}Webhooks
Instead of polling the Delivery Report endpoint, you can register a webhook URL and SimplySend will automatically POST the final delivery summary to your system when a campaign is complete.
How It Works
After you call POST /api-send, SimplySend syncs delivery statuses from the network in the background. Once all statuses are final, it fires a single POST request to your webhook URL with the campaign summary. You do not need to do anything — it happens automatically.
Events
SimplySend sends one of three event types depending on the campaign outcome:
| Event | Meaning |
|---|---|
| campaign.completed | All messages were delivered successfully. |
| campaign.partial | Some messages delivered, some failed or expired. Check summary.failed for the count. |
| campaign.failed | No messages were delivered. Alert your staff immediately. |
Webhook Payload
{
"event": "campaign.completed",
"campaign_id": "3f9a2b1c-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"sent_at": "2026-07-25T16:48:51.129Z",
"summary": {
"total": 150,
"delivered": 148,
"failed": 2,
"pending": 0,
"status": "Partial Success"
}
}
Payload Fields
| Field | Type | Description |
|---|---|---|
| event | string | One of campaign.completed, campaign.partial, or campaign.failed. |
| campaign_id | string | The same campaign_id returned by the Send SMS endpoint. |
| sent_at | string (ISO 8601) | Timestamp of when the webhook was fired. |
| summary.total | number | Total number of recipients in the campaign. |
| summary.delivered | number | Messages confirmed delivered by the network. |
| summary.failed | number | Messages that failed or expired without delivery confirmation. |
| summary.pending | number | Messages still awaiting a delivery receipt. This will be 0 when the webhook fires. |
| summary.status | string | Human-readable outcome: Completed, Partial Success, or Failed. |
Responding to a Webhook
Your endpoint must return HTTP 200 to acknowledge receipt. Return this even if you encounter an internal error processing the payload — SimplySend does not currently retry failed webhook deliveries.
@app.route('/simplysend/webhook', methods=['POST']) def handle_webhook(): data = request.json event = data['event'] summary = data['summary'] if event == 'campaign.completed': mark_campaign_success(data['campaign_id']) elif event == 'campaign.partial': flag_for_review(data['campaign_id'], summary['failed']) elif event == 'campaign.failed': alert_staff(data['campaign_id']) return '', 200 # Always return 200
Error Codes
All errors return a JSON object with an error field describing what went wrong.
{
"error": "A description of what went wrong."
}
| Status | Meaning | How to Fix |
|---|---|---|
| 200 | Success | Request completed successfully. |
| 400 | Bad Request | A required field is missing or invalid. Check the error message for the specific field. |
| 401 | Unauthorized | Your API key is missing, invalid, or has been deactivated. Check the X-API-Key header. |
| 402 | Insufficient Credits | Your account does not have enough SMS units for this request. Top up your balance and try again. |
| 404 | Not Found | The campaign_id does not exist or does not belong to your account. |
| 500 | Server Error | Something went wrong on our end. Contact SimplySend support if this persists. |
Limits
| Limit | Value | Notes |
|---|---|---|
| Recipients per request | 1,000 | For larger lists, split into multiple requests. |
| Message length | 160 characters per SMS part | Messages over 160 characters are split into multi-part SMS. Each part consumes one SMS unit. |
| Supported phone formats | Ghana numbers only | Local format (0244123456) or international format (+233244123456) both accepted. |
| Sender ID | Pre-approved only | Your Sender ID must be registered and approved before use. Contact SimplySend to register. |