Complete guide to integrating SMESS WhatsApp API into your application
SM-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Create and reveal keys from your client portal.
Register or log in, then create a key at API Keys.
SM-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Send messages via POST to /api/send using apikey, recipient and text.
The API returns HTTP 202 on success with a queue_id. Errors include an error_code and HTTP status.
All API requests require your API key. You can authenticate in three ways (in priority order):
| Method | How | Notes |
|---|---|---|
| POST field | apikey=SM-... |
Recommended for server-to-server integrations. |
| Header | X-API-Key: SM-... |
Preferred for cleaner logs. |
| Bearer | Authorization: Bearer SM-... |
Standard OAuth-style header. |
curl -X POST https://www.smess.io/api/send \
-H "X-API-Key: SM-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-d "recipient=+233244123456" \
-d "text=Hello World!"
POST https://www.smess.io/api/send
Messages are submitted to a queue and delivered by the background worker. The API returns HTTP 202 Accepted on success, not 200.
| Name | Type | Required | Description |
|---|---|---|---|
| apikey | string | Yes | Your API authentication key. Also accepted as X-API-Key or Authorization: Bearer header. Not api_key. |
| recipient | string | Yes | Phone number with country code (e.g., +233244123456). Not phone. |
| text | string | Yes* | Message text or media caption. Not message. *At least one content field is required. |
| priority | string/int | No | otp / urgent / high / normal (default) / bulk / low |
| idempotency_key | string | No | Unique key per send attempt. Replaying the same key within 5 minutes returns the original response without sending a duplicate. Recommended for OTPs. |
The endpoint detects the message type from the parameters you provide. Include only the parameters for the type you want to send:
| Type | Required parameter(s) |
|---|---|
| Text | text |
| Image | file (image URL) |
| Document | document (file URL) + optional filename |
| Video | video |
| Audio | audio |
| Location | latitude + longitude + optional label |
| Contact card | contact_name + contact_phone |
| Buttons | button1 + button1id (up to 3) |
| Copy code (OTP) | copycode + optional copytext |
| List menu | list_title + list_button + list_sections (JSON) |
curl -X POST https://www.smess.io/api/send \
-H "X-API-Key: SM-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-d "recipient=+233244123456" \
-d "text=Hello from SMESS!"
{
"success": true,
"message": "Message queued successfully. It will be sent by the queue worker.",
"data": {
"queue_id": 42,
"recipient": "+233244123456",
"message_type": "text",
"priority": 5,
"priority_label": "normal",
"status": "queued",
"timestamp": "2026-06-16 10:30:00",
"remaining_quota": 999,
"note": "Message will be sent by queue worker with rate limiting and spam prevention"
}
}
All message types use the same POST /api/send endpoint. The type is auto-detected from the parameters you send.
curl -X POST https://www.smess.io/api/send \
-H "X-API-Key: SM-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-d "recipient=+233244123456" \
-d "document=https://example.com/invoice.pdf" \
-d "filename=Invoice-2026.pdf" \
-d "text=Here is your invoice."
curl -X POST https://www.smess.io/api/send \
-H "X-API-Key: SM-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-d "recipient=+233244123456" \
-d "file=https://example.com/photo.jpg" \
-d "text=Check this out!"
curl -X POST https://www.smess.io/api/send \
-H "X-API-Key: SM-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-d "recipient=+233244123456" \
-d "text=Confirm your delivery?" \
-d "button1=Yes" \
-d "button1id=confirm" \
-d "button2=No" \
-d "button2id=cancel"
curl -X POST https://www.smess.io/api/send \
-H "X-API-Key: SM-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-d "recipient=+233244123456" \
-d "text=Your verification code is:" \
-d "copycode=482916" \
-d "copytext=Tap to Copy" \
-d "priority=otp" \
-d "idempotency_key=otp-user-123-1782466132"
curl -X POST https://www.smess.io/api/send \
-H "X-API-Key: SM-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-d "recipient=+233244123456" \
-d "latitude=5.6037" \
-d "longitude=-0.1870" \
-d "label=Accra Mall"
curl -X POST https://www.smess.io/api/send \
-H "X-API-Key: SM-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-d "recipient=+233244123456" \
-d "text=Please select a department:" \
-d "list_title=Contact Us" \
-d "list_button=View Departments" \
-d 'list_sections=[{"title":"Sales","rows":[{"title":"New Orders","description":"Place a new order","rowId":"sales_new"}]}]'
After queuing, track message status in the client portal or via the message detail API:
| Resource | URL | Purpose |
|---|---|---|
| Queue | /my-queue | Pending / processing / sent / failed messages |
| Message History | /my-messages | Delivered messages and delivery receipts |
queue_id returned in the 202 response and use it to correlate with status updates in your dashboard or webhooks.
The API returns JSON error responses with an HTTP status code and an error_code when available:
| 400 | Bad Request — missing or invalid parameters (e.g., wrong phone format) |
| 401 | Unauthorized — API key missing or invalid (INVALID_KEY) |
| 402 | Payment Required — quota exceeded (QUOTA_EXCEEDED) or subscription/trial expired |
| 403 | Forbidden — key inactive/revoked (KEY_INACTIVE) or account suspended |
| 413 | Payload Too Large — media file exceeds your plan limit |
| 429 | Too Many Requests — per-minute rate limit or per-recipient cooldown (OTP_COOLDOWN) |
| 503 | Service Unavailable — WhatsApp connection not ready (WHATSAPP_DISCONNECTED / NOT_ACTIVATED) |
{
"success": false,
"error": "Invalid API key",
"error_code": "INVALID_KEY",
"code": 401
}
Limits are per API key and depend on your plan:
| Limit | Starter | Growth | Enterprise |
|---|---|---|---|
| API submissions / minute | 60 | 300 | 1000 |
| Document/media max size | 25 MB | 50 MB | 100 MB |
| Per-recipient minimum gap | 60 seconds (configurable 0–600s per key) | ||
| Per-recipient daily cap | 50 messages / recipient / day | ||
priority=bulk and submit via POST /api/bulk (Growth+). The queue worker spaces out delivery automatically.
Common mistakes that cause API errors:
The server did not receive a valid key. Common causes:
| ❌ Wrong (will fail) | ✅ Correct |
|---|---|
api_key (with underscore) | apikey |
key or token | apikey / X-API-Key / Authorization: Bearer |
JSON body (Content-Type: application/json) | application/x-www-form-urlencoded or multipart |
Query string ?apikey=... | POST field or header (query string is deprecated and logged) |
| ❌ Wrong (will fail) | ✅ Correct |
|---|---|
phone, number, to | recipient |
message, msg, body | text |
image, photo | file (images) or document (any file) |
curl -X POST https://www.smess.io/api/send \
-H "X-API-Key: SM-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-d "recipient=+233244123456" \
-d "text=Hello, this works!"
# WRONG - these parameter names are NOT accepted
curl -X POST https://www.smess.io/api/send \
-H "Content-Type: application/json" \
-d '{"api_key":"SM-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX","phone":"+233244123456","message":"This will fail"}'