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.

POST https://sozuri.net/api/v1/messaging/sendpremium
What you earn, and what it costs to start: shortcode setup and monthly fees, the volume-tiered revenue share, and a calculator that shows your net per message — see Premium SMS pricing. The same rates apply to both on-demand and subscription messages.

How the subscription flow works

  1. 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.
  2. Sozuri pushes an activation webhook with the subscriber’s number and the keyword they used.
  3. You send recurring premium content via the API. Each message triggers a charge.
  4. Delivery and unsubscribe events stream to your webhook as they happen.
Subscription premium SMS requires an approved premium shortcode and a subscription billing arrangement with each carrier. Apply from your dashboard at Numbers › Apply for a shortcode — our team handles the carrier paperwork.

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
FieldRequiredTypeDescription
projectYesStringThe Sozuri project that owns the API key.
fromYesStringYour premium shortcode.
numberYesStringThe subscriber’s phone in E.164. 0722-503-129 normalises to 254722503129.
channelNoStringAccepted and ignored. Kept for compatibility with older integrations.
typeNoStringAccepted and ignored — the product type comes from the offer itself.
keywordRecommendedStringThe 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.
messageYesStringThe premium content to send.
campaignNoStringOptional label for reporting.
apiKeyStringYour project API key. Recommended: send as a Bearer token instead.

Send a premium message: response

FieldTypeDescription
messageData.messagesNumberTotal messages accepted.
recipients[].messageIdStringUnique Sozuri ID for this message.
recipients[].toStringThe recipient’s phone number, normalised.
recipients[].statusStringAcceptance status — not the final delivery status.
recipients[].statusCodeStringNumeric status — see status codes.
recipients[].messagePartNumberSMS parts used.
recipients[].typeStringAlways 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.

PurposeEndpointRequired 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.

Carriers require explicit user consent before you activate a subscriber on their behalf. Keep proof of consent (form submission, voice call recording, etc.) — this is what carriers audit when disputes arise.

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.

Nothing is sent until you switch the schedule on, and a missed slot is not caught up later — a reverse-billed “good morning” that arrives at 11:00 is a refund request. Message length is a price: a message is charged per 160-character part, so a 200-character tip costs your subscriber two parts.

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"
}

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.

ConditionHTTPResponse body
Trying to activate a subscriber who is already active on this premium service. 400
{
    "status": "error",
    "description": "Subscriber already Exists"
}
Trying to deactivate a number that was never subscribed to this premium service. 400
{
    "status": "error",
    "description": "Unknown Subscriber"
}
Trying to deactivate a subscriber who is already inactive. 400
{
    "status": "error",
    "description": "Subscriber is already Inactive"
}
Keyword doesn’t match an active premium service on this project. 400
{
    "status": "error",
    "description": "Unknown, Expired, or Inactive Premium Service"
}
Destination phone number is malformed or not in supported E.164 format. 400
{
    "status": "error",
    "description": "Unsupported Number"
}
For status code reference see Status codes & response envelopes. For asynchronous delivery callbacks see Delivery webhook statuses.

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.

📖
23546
Daily Quote
“The best way out is always through.” — Robert Frost. Send STOP to unsubscribe. 07:00

Health & wellness tips

Weekly maternal-health, HIV-adherence or chronic-care reminders — works on every phone, no data needed.

💊
21456
AfyaTips
AfyaTip: Week 24. Your baby is now about 30 cm long. Visit the clinic for your second trimester check-up this week. 08:00

Agronomy & market prices

Daily commodity prices for farmers, weather alerts, planting tips — high-value content for rural subscribers.

🌾
40234
ShambaPrices
Today’s Nairobi prices:
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.