Developers

Communication API

Send SMS and bulk email from your systems using API keys. Check credit balance, buy credits via M-Pesa, and receive delivery webhooks when configured in the app.

Quick start

  1. Sign in to World Ledgers and open Communication → SMS.
  2. Generate an API key in the API Integration panel.
  3. Optionally set a webhook URL and secret for delivery notifications.
  4. Call the endpoints below with your API key.

Postman sandbox (no real SMS)

Import the collection from postman/World-Ledgers-Communication-API.postman_collection.json in this repository. Seed the sandbox firm, then use the test API key below — messages are accepted and statuses are simulated immediately; nothing is sent to a live SMS provider.

php artisan db:seed --class=CommunicationApiSandboxSeeder

API key: wl_test_communication_sms_sandbox
Base URL: https://www.worldledgers.com/api/v1/communication

Sandbox test numbers:

  • 254712345678 — simulated delivery success
  • 254700000099 — simulated delivery failure
  • 254700000088 — simulated insufficient credits

Endpoints

Method Path Description
GET/sms-credits/balanceCurrent SMS credit balance and firm rate
POST/sms-credits/purchaseStart M-Pesa STK to buy credits
GET/sms-credits/purchase/{payment_id}Poll purchase status and applied credits
POST/smsSchedule SMS to one or more numbers
POST/emailSchedule bulk email
GET/sms/{message_id}SMS delivery status
GET/email/{message_id}Email delivery status

Base URL

https://www.worldledgers.com/api/v1/communication

Authentication

Include your API key on every request using either header:

X-API-Key: wl_comm_your_api_key_here

or

Authorization: Bearer wl_comm_your_api_key_here

SMS credit balance

GET /sms-credits/balance

Returns the current SMS credit balance for the firm tied to your API key, plus the KES rate per credit.

Example request
curl "https://www.worldledgers.com/api/v1/communication/sms-credits/balance" \
  -H "X-API-Key: wl_comm_your_api_key_here"
Success response 200
{
  "status": "success",
  "data": {
    "sms_credits": 125.5,
    "sms_rate": 1.8,
    "currency": "KES"
  }
}

sms_rate is KES per 1 SMS credit (set by platform admins per firm). Credits granted on purchase = amount paid ÷ sms_rate.

Buy SMS credits

POST /sms-credits/purchase

{
  "phone": "0712345678",
  "amount": 500
}

Initiates M-Pesa STK for amount in KES. Poll purchase status after the customer pays:

GET /sms-credits/purchase/{payment_id}

Purchase status response
{
  "status": "success",
  "data": {
    "payment_status": "Received",
    "amount_kes": 500,
    "sms_rate": 1.8,
    "sms_credits_applied": 277.7778,
    "firm_sms_credits": 403.2778,
    "estimated_credits": 277.7778
  }
}

Send SMS

POST /sms

Schedule one or more SMS messages. Messages are queued and sent by the platform scheduler.

Request body
{
  "message": "Hello {first_name}, your balance is {account_balance}.",
  "recipients": ["254712345678", "0712345678"],
  "send_at": "2026-06-10 14:00:00",
  "reference": "invoice-reminder-42"
}
  • message (required) — up to 1000 characters.
  • recipients (required) — array of Kenya mobile numbers (2547…, 07…, or 7…).
  • send_at (optional) — schedule for later. Defaults to now.
  • reference (optional) — your correlation ID, echoed in webhooks.

Message placeholders {first_name}, {last_name}, {name}, and {account_balance} are filled automatically when the recipient matches a client or address-book contact in your firm.

Success response 202
{
  "status": "success",
  "message": "SMS scheduled successfully.",
  "data": {
    "blast_id": "SMS-…",
    "scheduled": 2,
    "skipped": [],
    "reference": "invoice-reminder-42"
  }
}

Send bulk email

POST /email

Schedule HTML or plain-text emails to multiple recipients.

Request body
{
  "subject": "Payment reminder",
  "message": "<p>Hello {first_name}, please pay your invoice.</p>",
  "recipients": ["customer@example.com", "billing@example.com"],
  "send_at": "2026-06-10 09:00:00",
  "reference": "billing-campaign-june"
}

Placeholders in the message body are resolved the same way as SMS when a matching contact exists.

Success response 202
{
  "status": "success",
  "message": "Emails scheduled successfully.",
  "data": {
    "blast_id": "MAIL-…",
    "scheduled": 2,
    "skipped": [],
    "reference": "billing-campaign-june"
  }
}

Check message status

GET /sms/{message_id}  ·  GET /email/{message_id}

Poll delivery status for a message created via the API.

{
  "status": "success",
  "data": {
    "type": "sms",
    "event": "communication.sms.delivered",
    "message_id": 123,
    "blast_id": "SMS-…",
    "reference": "invoice-reminder-42",
    "recipient": "254712345678",
    "status": "delivered",
    "status_code": 1,
    "response": "Success"
  }
}

Status codes: 0 pending, 3 processing, 1 delivered, 2 failed.

Webhooks

When a webhook URL is configured in the app, World Ledgers sends a POST request for each status change on API-sent messages.

Headers
  • Content-Type: application/json
  • X-WL-Event — event name (e.g. communication.sms.delivered)
  • X-WL-Signaturesha256=<hmac> when a webhook secret is set
Example payload
{
  "type": "sms",
  "event": "communication.sms.delivered",
  "message_id": 123,
  "blast_id": "SMS-…",
  "reference": "invoice-reminder-42",
  "recipient": "254712345678",
  "status": "delivered",
  "status_code": 1,
  "response": "Success",
  "firm_id": 1,
  "timestamp": "2026-06-10T14:05:00+03:00"
}

Email events include communication.email.delivered, communication.email.failed, communication.email.opened, and communication.email.clicked.

Verify signature
expected = 'sha256=' + HMAC_SHA256(raw_request_body, webhook_secret)
valid = timing_safe_equal(expected, request.headers['X-WL-Signature'])

Error responses

401 — Missing or invalid API key
403 — Account suspended or expired
422 — Validation error or no valid recipients
429 — Rate limit exceeded

Example (cURL)

curl "https://www.worldledgers.com/api/v1/communication/sms-credits/balance" \
  -H "X-API-Key: wl_comm_your_api_key_here"

curl -X POST "https://www.worldledgers.com/api/v1/communication/sms" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: wl_comm_your_api_key_here" \
  -d '{
    "message": "Hello {name}, your payment is due.",
    "recipients": ["254712345678"],
    "reference": "demo-001"
  }'