Subscription premium SMS
Subscription premium SMS lets you bill subscribers on a recurring schedule — daily, weekly or monthly — for content delivered to their phone. Customers opt in via your shortcode, and the carrier charges them automatically until they opt out.
- How the subscription flow works
- Send a premium message: request
- Send a premium message: response
- Sample send-message request
- Activate or deactivate a subscriber
- Subscriber webhooks (activate, deactivate, consent, delivery)
- Error responses
How the subscription flow works
- A subscriber opts in by texting your keyword (e.g.
JOIN) to your shortcode — or you call the activate endpoint on their behalf with explicit consent. - Sozuri pushes an
activationwebhook with the subscriber’s number and the keyword they used. - You send recurring premium content via the API. Each message triggers a charge.
- Delivery and unsubscribe events stream to your webhook as they happen.
Send a premium message: request parameters
Required headers
POST /api/v1/messaging/sendpremium HTTP/1.1
Host: sozuri.net
Authorization: Bearer Your_Project_API_KEY
Content-Type: application/json
Accept: application/json
| Field | Required | Type | Description |
|---|---|---|---|
| project | Yes | String | The Sozuri project that owns the API key. |
| from | Yes | String | Your premium shortcode. |
| number | Yes | String | The subscriber’s phone in E.164. 0722-503-129 normalises to 254722503129. |
| channel | No | String | Accepted and ignored. Kept for compatibility with older integrations. |
| type | No | String | Accepted and ignored — the product type comes from the offer itself. |
| keyword | Recommended | String | The activation keyword of the service. Required on subscribe and unsubscribe; on a send it is what picks the offer when one shortcode carries several. premium_id is accepted instead. |
| message | Yes | String | The premium content to send. |
| campaign | No | String | Optional label for reporting. |
| apiKey | — | String | Your project API key. Recommended: send as a Bearer token instead. |
Send a premium message: response
| Field | Type | Description |
|---|---|---|
| messageData.messages | Number | Total messages accepted. |
| recipients[].messageId | String | Unique Sozuri ID for this message. |
| recipients[].to | String | The recipient’s phone number, normalised. |
| recipients[].status | String | Acceptance status — not the final delivery status. |
| recipients[].statusCode | String | Numeric status — see status codes. |
| recipients[].messagePart | Number | SMS parts used. |
| recipients[].type | String | Always subscription here. |
Sample request
POST /api/v1/messaging/sendpremium HTTP/1.1
Host: sozuri.net
Authorization: Bearer LOx5JPdqf0lvf.......R9X9XDJ4PFxRqVrt9dx83cWiwfTQMF
Content-Type: application/json
Accept: application/json
{
"project": "my project",
"from": "23546",
"number": "2547251642xx",
"campaign": "Daily Quote",
"channel": "premium",
"message": "Today's quote: The best way out is always through. - Robert Frost.",
"type": "subscription",
"keyword": "Omoka"
}
Sample JSON response
{
"messageData": { "messages": 1 },
"recipients": [
{
"messageId": "MSGBLK6012A7E8B90A21611835368",
"to": "2547251642xx",
"status": "accepted",
"statusCode": "11",
"messagePart": 1,
"type": "subscription"
}
]
}
Add or remove a subscriber
Subscribers normally opt in themselves by texting your activation keyword to your shortcode. You can also
add one yourself — for example when somebody opts in on a web form — using the
subscribe endpoint. These are separate endpoints from sending, not a
type on the send call.
| Purpose | Endpoint | Required fields |
|---|---|---|
| Opt a number in | POST /api/v1/messaging/subscribe | project, number, keyword |
| Opt a number out | POST /api/v1/messaging/unsubscribe | project, number, keyword |
| Send to a subscriber | POST /api/v1/messaging/sendpremium | project, number, message, and from or keyword |
Subscribe
curl -X POST https://sozuri.net/api/v1/messaging/subscribe \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer Your_Project_API_KEY' \
-d '{
"project": "my project",
"keyword": "JOIN",
"number": "0722503129",
"name": "Jane Doe"
}'
{
"project": "my project",
"shortcode": "20555",
"keyword": "JOIN",
"number": "254722503129",
"network": "safaricom",
"type": "subscribe",
"status": "pending",
"statusCode": "112",
"description": "Your request for the service is under process."
}
status is pending, not active, and that is not a delay in our
system. The carrier owns consent: it asks the subscriber to confirm on their handset, and the
subscription only exists once they accept. You will receive an activation
webhook at that point — that is the event to act on. Until then the number appears as
Pending in your dashboard and cannot be sent to.
Unsubscribe
curl -X POST https://sozuri.net/api/v1/messaging/unsubscribe \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer Your_Project_API_KEY' \
-d '{
"project": "my project",
"keyword": "JOIN",
"number": "0722503129"
}'
A subscriber can also opt out themselves by texting your deactivation keyword (usually STOP) to
your shortcode, and the carrier can deactivate them — for churn, or when an offer is withdrawn. All three
routes produce a deactivation webhook.
Let Sozuri send on a schedule
You do not need your own cron job or content system. On Premium Services in your dashboard, a subscription service has a Sending schedule panel where you set:
- A cadence — every day at 07:00, weekdays, Mondays, the 1st of the month, or any cron expression, evaluated in your own timezone.
- What gets sent — either one fixed message, or a list with one message per line. A list is sent in order, one per run, and where it got to is remembered: paste 90 tips once and send one a day for three months.
- The price per message, charged to the subscriber.
Placeholders {name}, {msisdn}, {date}, {time},
{offer} and {shortcode} are substituted per recipient. Every send appears in your
outbox with a run id, and each one raises a delivery webhook exactly as an API send does.
Subscriber webhooks
You’ll receive four kinds of asynchronous webhooks. Configure the receiving URL from Manage API › Callback URLs.
1. Activation
Fires when a subscriber opts in — either by texting your keyword to your shortcode, or after a successful activate API call.
{
"project": "yourproject_name",
"shortcode": "25145",
"keyword": "JOIN",
"number": "2547251xxxxx",
"network": "safaricom",
"type": "activation",
"status": "success",
"timestamp": "1603713484"
}
2. Deactivation
Fires when a subscriber opts out — via your STOP keyword, USSD menu or carrier dashboard.
{
"project": "yourproject_name",
"shortcode": "25145",
"keyword": "JOIN",
"number": "2547251xxxxx",
"network": "safaricom",
"type": "deactivation",
"status": "success",
"timestamp": "1603713484"
}
3. Consent
Fires after you call the activate API. Status is success if the carrier accepted the activation, or failure if the subscriber rejected the consent prompt.
{
"project": "yourproject_name",
"shortcode": "25145",
"keyword": "JOIN",
"number": "2547251xxxxx",
"network": "safaricom",
"type": "consent",
"status": "failure",
"timestamp": "1603713484"
}
4. Delivery status
Fires for each premium message you sent — one event per state change.
{
"project": "yourproject_name",
"shortcode": "25145",
"keyword": "JOIN",
"number": "2547251xxxxx",
"network": "safaricom",
"type": "premiumDelivery",
"status": "success",
"timestamp": "1603713484"
}
Optional callback authentication
Your project’s Auth Key is included in every callback body as authKey, alongside an X-Sozuri-Signature HMAC header, so you can verify a webhook is genuinely from Sozuri. Both live under Manage API › Callback URLs › Webhook security — see Verifying authenticity.
Error responses
Subscription premium SMS uses the SDP error envelope: { "status": "error", "description": "…" }. Auth errors (Unknown project.) follow the SMS envelope and are documented on the Authentication page.
| Condition | HTTP | Response body |
|---|---|---|
| Trying to activate a subscriber who is already active on this premium service. | 400 | |
| Trying to deactivate a number that was never subscribed to this premium service. | 400 | |
| Trying to deactivate a subscriber who is already inactive. | 400 | |
| Keyword doesn’t match an active premium service on this project. | 400 | |
| Destination phone number is malformed or not in supported E.164 format. | 400 | |
Use cases
The recurring SMS services that thrive on premium subscriptions across Africa.
Daily content (quotes, devotionals, jokes)
Subscriber pays a daily fee to receive one short message a day — the original mobile content business model, still huge.
Health & wellness tips
Weekly maternal-health, HIV-adherence or chronic-care reminders — works on every phone, no data needed.
Agronomy & market prices
Daily commodity prices for farmers, weather alerts, planting tips — high-value content for rural subscribers.
Maize KES 4,200 / 90kg bag
Beans KES 9,800 / 90kg
Milk KES 55 / litre
Rain expected in Eldoret tomorrow. 06:00
Sports & betting tips
Tipsters and sports networks monetise daily picks via opt-in subscriptions.
Launch a recurring SMS service.
We’ll set up the shortcode, register your keyword and handle billing reconciliation with the carrier.