Send bulk SMS
Send campaigns and announcements to thousands of recipients, in safe, resumable batches.
One request sends one message to up to 1,000 recipients. For bigger lists, send in batches.
One batch
curl https://api.softlinksms.co.ke/api/v1/sms \
-H "X-Api-Key: $SOFTLINK_API_KEY" \
-H "Idempotency-Key: spring-sale-batch-0" \
-H "Content-Type: application/json" \
-d '{
"recipients": ["+254712345678", "0798765432", "254701234567"],
"message": "Spring sale: 20% off everything until Sunday. Reply STOP to opt out."
}'What happens:
- Every number is validated first. If any number is invalid, the whole request is rejected with
400and the bad numbers listed, and nothing is sent or charged. See Phone numbers. - Duplicates are removed. Each unique number gets one message.
- The whole batch is charged at once from your wallet. If the balance can't cover it, you get
402 insufficient_balanceand nothing is sent. - You get one object back for the whole send: its
batch_id,recipients,total_priceandcurrency, and amessageslist with one message per recipient. Every message and webhook event carries the samebatch_id.
Many batches
Split the list into chunks of 1,000 and give each chunk a stable idempotency key, such as campaign id plus chunk number. If your job crashes halfway, rerun it from the start: chunks that already went out are replayed from their keys rather than sent again.
import os
import time
import requests
API = "https://api.softlinksms.co.ke/api/v1/sms"
HEADERS = {"X-Api-Key": os.environ["SOFTLINK_API_KEY"]}
def send_campaign(campaign_id: str, numbers: list[str], body: str) -> None:
for start in range(0, len(numbers), 1000):
chunk = numbers[start : start + 1000]
while True:
response = requests.post(
API,
headers={**HEADERS, "Idempotency-Key": f"{campaign_id}-{start // 1000}"},
json={"recipients": chunk, "body": body},
timeout=30,
)
if response.status_code == 429:
time.sleep(int(response.headers.get("Retry-After", "1")))
continue
response.raise_for_status()
breakAt 30 send requests per second per account (see Rate limits), that's up to 30,000 recipients a second.
Promotional rules
Bulk messages are usually promotional, the default. Promotional SMS in Kenya must only go to people who agreed to receive it and must tell them how to stop:
- Keep your own opt-in records.
- Include opt-out instructions, such as "Reply STOP to opt out".
- Honour opt-outs before your next send.
Don't send promotions as transactional to get around these rules; it gets transactional access revoked.
After the send
Messages move from pending to sent within seconds, then to delivered or failed as networks report back. For a campaign, webhooks are far cheaper than polling 1,000 messages. Use batch_id to group results by send.