Skip to main content

Overview

The SMS service provides comprehensive messaging capabilities including bulk SMS, two-way messaging, delivery reports, opt-out management, and subscription notifications.

Service Status

Check SMS Service Status

curl http://localhost:8000/sms/
service
string
Service name (“sms”)
status
string
Service status (“ready”)
Response Example
{
  "service": "sms",
  "status": "ready"
}

Sending SMS

Send Bulk SMS

Send SMS messages to one or more recipients using the bulk SMS API.
curl "http://localhost:8000/sms/invoke-bulk-sms?phone=254711XXXYYY&message=Hello%20World"
phone
string
required
Recipient phone number (without + prefix)Example: 254711XXXYYY
message
string
default:"Hello from Africa's Talking!"
Message content to send
Response Example
{
  "message": "SMS sent to +254711XXXYYY",
  "response": {
    "SMSMessageData": {
      "Message": "Sent to 1/1 Total Cost: KES 0.8000",
      "Recipients": [
        {
          "statusCode": 101,
          "number": "+254711XXXYYY",
          "cost": "KES 0.8000",
          "status": "Success",
          "messageId": "ATXid_..."
        }
      ]
    }
  }
}
Error Response
{
  "error": "Missing 'phone' query parameter"
}

Send Two-Way SMS

Send SMS using a dedicated shortcode that supports two-way messaging.
curl "http://localhost:8000/sms/invoke-twoway-sms?phone=254711XXXYYY&message=Hello%20World"
phone
string
required
Recipient phone number (without + prefix)
message
string
default:"Hello from Africa's Talking!"
Message content to send
Response Example
{
  "message": "SMS sent to +254711XXXYYY",
  "response": {
    "SMSMessageData": {
      "Message": "Sent to 1/1 Total Cost: KES 0.8000",
      "Recipients": [...]
    }
  }
}

Webhooks

Two-Way SMS Callback

Receive and respond to incoming SMS messages from users.
curl -X POST http://localhost:8000/sms/twoway \
  -d "linkId=SampleLinkId123" \
  -d "text=Hello" \
  -d "to=12345" \
  -d "id=ATSid_123" \
  -d "date=2026-03-04+10:30:00" \
  -d "from=%2B254711000111"
Unique identifier linking related messages
text
string
required
Message content from the user
to
string
required
Shortcode the message was sent to
id
string
required
Africa’s Talking message ID
date
string
required
Timestamp when message was received
from
string
required
Sender’s phone number
Implementation
# From routes/sms.py:56-77
@sms_bp.route("/twoway", methods=["POST"])
def twoway_callback():
    linkId = request.values.get("linkId")
    text = request.values.get("text")
    to = request.values.get("to")
    msg_id = request.values.get("id")
    date = request.values.get("date")
    sender = request.values.get("from")

    if not linkId or not text or not to or not msg_id or not date or not sender:
        return "BAD", 400
    
    print(f"Received 2-way SMS from {sender}: {text}")

    # Respond with a new SMS back to the sender
    send_twoway_sms(
        message=f'This is a response to: "{text}"',
        recipient=sender,
    )

    return "GOOD", 200
Response
  • Success: "GOOD" with status code 200
  • Error: "BAD" with status code 400

Delivery Reports

Receive notifications about SMS delivery status.
curl -X POST http://localhost:8000/sms/delivery-reports \
  -d "id=ATXid_123" \
  -d "status=Success" \
  -d "phoneNumber=%2B254711XXXYYY" \
  -d "networkCode=63902" \
  -d "failureReason=" \
  -d "retryCount=0"
id
string
required
Message ID from the send response
status
string
required
Delivery status (e.g., “Success”, “Failed”)
phoneNumber
string
required
Recipient’s phone number
networkCode
string
required
Mobile network operator code
failureReason
string
Reason for failure (if status is “Failed”)
retryCount
string
Number of retry attempts
Implementation
# From routes/sms.py:80-100
@sms_bp.route("/delivery-reports", methods=["POST"])
def sms_delivery_report():
    payload = {key: request.values.get(key) for key in request.values.keys()}

    print("📩 SMS Delivery Report Received:")
    for key, value in payload.items():
        print(f"   {key}: {value}")

    return Response("OK", status=200)
Response
  • Status: 200 OK
  • Body: "OK"

Opt-Out Notifications

Receive notifications when users opt out of bulk SMS.
curl -X POST http://localhost:8000/sms/opt-out \
  -d "senderId=MyBrand" \
  -d "phoneNumber=%2B254711XXXYYY"
senderId
string
required
Your sender ID or brand name
phoneNumber
string
required
Phone number that opted out
Implementation
# From routes/sms.py:103-119
@sms_bp.route("/opt-out", methods=["POST"])
def sms_opt_out():
    payload = {key: request.values.get(key) for key in request.values.keys()}

    print("🚫 SMS Opt-Out Notification Received:")
    for key, value in payload.items():
        print(f"   {key}: {value}")

    return Response("OK", status=200)
Response
  • Status: 200 OK
  • Body: "OK"

Subscription Notifications

Receive notifications about premium SMS subscription updates.
curl -X POST http://localhost:8000/sms/subscription \
  -d "phoneNumber=%2B254711000111" \
  -d "shortCode=12345" \
  -d "keyword=NEWS" \
  -d "updateType=addition"
phoneNumber
string
required
Subscriber’s phone number
shortCode
string
required
Premium shortcode
keyword
string
required
Subscription keyword
updateType
string
required
Type of update: "addition" or "deletion"
Implementation
# From routes/sms.py:122-151
@sms_bp.route("/subscription", methods=["POST"])
def sms_subscription():
    payload = {key: request.values.get(key) for key in request.values.keys()}

    print("⭐ SMS Subscription Notification Received:")
    for key, value in payload.items():
        print(f"   {key}: {value}")

    # Extract values
    phone_number = payload.get("phoneNumber")
    short_code = payload.get("shortCode")
    keyword = payload.get("keyword")
    update_type = payload.get("updateType")

    print(
        f"➡️ Subscription update for {phone_number}: "
        f"{update_type.upper()} to '{keyword}' on shortcode {short_code}"
    )

    return Response("OK", status=200)
Response
  • Status: 200 OK
  • Body: "OK"

Next Steps

Voice Service

Learn how to make calls and handle voice events

Airtime Service

Send airtime to users programmatically

Build docs developers (and LLMs) love