On-demand premium SMS lets you charge subscribers per-message for content they request — quizzes, sports scores, news clips, jokes, horoscopes. The customer texts a keyword to your shortcode, you reply with the paid content, and the carrier collects the fee on your behalf.

POST https://sozuri.net/api/v1/premium

How the flow works

  1. The subscriber texts your keyword (e.g. GOAL) to your shortcode.
  2. Sozuri pushes an incoming webhook to your application with a linkId identifying this request.
  3. You reply via the API, passing the same linkId back — this is what triggers the premium charge.
  4. Sozuri sends a delivery webhook when the premium SMS reaches the subscriber and the carrier confirms the charge.
On-demand premium SMS requires an approved premium shortcode and registered keywords. Apply for both from your dashboard at Numbers › Apply for a shortcode.
Required headers
POST /api/v1/premium HTTP/1.1
Host: sozuri.net
Authorization: Bearer Your_Project_API_KEY
Content-Type: application/json
Accept: application/json

Request parameters

FieldRequiredTypeDescription
projectYesStringThe Sozuri project that owns the API key.
fromYesStringYour premium shortcode (e.g. 23546).
toYesStringThe subscriber’s phone number in E.164. 0722-503-129 is normalised to 254722503129.
channelYesStringAlways premium.
typeYesStringAlways ondemand on this endpoint.
messageYesStringThe premium content you’re sending the subscriber.
keywordYesStringThe keyword the subscriber sent in to request this content (e.g. OMOKA).
linkIdYesStringThe ID Sozuri delivered in the incoming-keyword webhook. Mandatory for billing this message as on-demand.
campaignNoStringOptional label for grouping reports.
apiKeyStringYour project API key. Recommended: pass as a Bearer token instead.

Response parameters

Synchronous JSON response confirming the premium message was accepted for delivery:

FieldTypeDescription
messageData.messagesNumberTotal messages accepted.
recipients[].messageIdStringUnique Sozuri ID for this message.
recipients[].toStringThe recipient’s phone number.
recipients[].statusStringAcceptance status — accepted, unknown_number etc. Not the final delivery status.
recipients[].statusCodeStringNumeric status — see status codes.
recipients[].messagePartNumberSMS parts used. One GSM-7 part is 160 characters.
recipients[].keywordStringEchoes back the keyword.
recipients[].typeStringAlways ondemand here.

Sample request

POST /api/v1/premium HTTP/1.1
Host: sozuri.net
Authorization: Bearer LOx5JPdqf0lvf.......R9X9XDJ4PFxRqVrt9dx83cWiwfTQMF
Content-Type: application/json
Accept: application/json

{
    "project": "my project",
    "from": "23546",
    "to": "2547251642xx",
    "campaign": "Promo Nai",
    "channel": "premium",
    "message": "Test SMS.",
    "type": "ondemand",
    "linkId": "54785454",
    "keyword": "Omoka"
}
POST /api/v1/premium HTTP/1.1
Host: sozuri.net
Authorization: Bearer LOx5JPdqf0lvf45EZAQMJ.......SUzyxR9X9XDJ4PFxRqVrt9dx83cWiwfTQMF
Content-Type: application/json
Accept: application/xml

<request>
    <project>my project</project>
    <from>23546</from>
    <to>2547251642xx</to>
    <campaign>Promo Nai</campaign>
    <channel>premium</channel>
    <message>Test SMS.</message>
    <type>ondemand</type>
    <linkId>54785454</linkId>
    <keyword>Omoka</keyword>
</request>
<?php

$curl = curl_init();
curl_setopt_array($curl, [
    CURLOPT_URL => "https://sozuri.net/api/v1/premium",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_POSTFIELDS => json_encode([
        "project"  => "my project",
        "from"     => "23546",
        "to"       => "2547251642xx",
        "campaign" => "Promo Nai",
        "channel"  => "premium",
        "message"  => "Test SMS.",
        "type"     => "ondemand",
        "linkId"   => "54785454",
        "keyword"  => "Omoka",
    ]),
    CURLOPT_HTTPHEADER => [
        "Accept: application/json",
        "Authorization: Bearer LOx5JPdqf0lvf45EZAQMJm85OSUzyxR9X9XDJ4PFxRqVrt9dx83cWiwfTQMF",
        "Content-Type: application/json",
    ],
]);
echo curl_exec($curl);
curl_close($curl);
const response = await fetch("https://sozuri.net/api/v1/premium", {
    method: "POST",
    headers: {
        "Authorization": "Bearer LOx5JPdqf0lvf45EZAQMJm85OSUzyxR9X9XDJ4PFxRqVrt9dx83cWiwfTQMF",
        "Content-Type": "application/json",
        "Accept": "application/json"
    },
    body: JSON.stringify({
        project: "my project",
        from: "23546",
        to: "2547251642xx",
        campaign: "Promo Nai",
        channel: "premium",
        message: "Test SMS.",
        type: "ondemand",
        linkId: "54785454",
        keyword: "Omoka"
    })
});
console.log(await response.json());
require 'uri'
require 'net/http'
require 'json'

uri  = URI("https://sozuri.net/api/v1/premium")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer LOx5JPdqf0lvf45EZAQMJm85OSUzyxR9X9XDJ4PFxRqVrt9dx83cWiwfTQMF"
request["Content-Type"]  = "application/json"
request["Accept"]        = "application/json"
request.body = {
    project: "my project", from: "23546", to: "2547251642xx",
    campaign: "Promo Nai", channel: "premium", message: "Test SMS.",
    type: "ondemand", linkId: "54785454", keyword: "Omoka"
}.to_json

puts http.request(request).body
import requests

response = requests.post(
    "https://sozuri.net/api/v1/premium",
    headers={
        "Authorization": "Bearer LOx5JPdqf0lvf45EZAQMJm85OSUzyxR9X9XDJ4PFxRqVrt9dx83cWiwfTQMF",
        "Content-Type": "application/json",
        "Accept": "application/json",
    },
    json={
        "project": "my project", "from": "23546", "to": "2547251642xx",
        "campaign": "Promo Nai", "channel": "premium", "message": "Test SMS.",
        "type": "ondemand", "linkId": "54785454", "keyword": "Omoka",
    },
)
print(response.json())
HttpResponse<String> response = Unirest.post("https://sozuri.net/api/v1/premium")
    .header("Authorization", "Bearer LOx5JPdqf0lvf45EZAQMJm85OSUzyxR9X9XDJ4PFxRqVrt9dx83cWiwfTQMF")
    .header("Content-Type",  "application/json")
    .header("Accept",        "application/json")
    .body("{\"project\":\"my project\",\"from\":\"23546\",\"to\":\"2547251642xx\","
        + "\"campaign\":\"Promo Nai\",\"channel\":\"premium\",\"message\":\"Test SMS.\","
        + "\"type\":\"ondemand\",\"linkId\":\"54785454\",\"keyword\":\"Omoka\"}")
    .asString();
var client  = new RestClient("https://sozuri.net/api/v1/premium");
var request = new RestRequest(Method.POST);
request.AddHeader("Accept",        "application/json");
request.AddHeader("Content-Type",  "application/json");
request.AddHeader("Authorization", "Bearer LOx5JPdqf0lvf45EZAQMJm85OSUzyxR9X9XDJ4PFxRqVrt9dx83cWiwfTQMF");
request.AddParameter("application/json",
    "{\"project\":\"my project\",\"from\":\"23546\",\"to\":\"2547251642xx\","
  + "\"campaign\":\"Promo Nai\",\"channel\":\"premium\",\"message\":\"Test SMS.\","
  + "\"type\":\"ondemand\",\"linkId\":\"54785454\",\"keyword\":\"Omoka\"}",
    ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
curl -X POST https://sozuri.net/api/v1/premium \
    -H 'Content-Type: application/json' \
    -H 'Accept: application/json' \
    -H 'Authorization: Bearer LOx5JPdqf0lvf45EZAQMJm85OSUzyxR9X9XDJ4PFxRqVrt9dx83cWiwfTQMF' \
    -d '{
        "project": "my project",
        "from": "23546",
        "to": "2547251642xx",
        "campaign": "Promo Nai",
        "channel": "premium",
        "message": "Test SMS.",
        "type": "ondemand",
        "linkId": "54785454",
        "keyword": "Omoka"
    }'
Sample JSON response
{
    "messageData": { "messages": 1 },
    "recipients": [
        {
            "messageId": "MSGBLK6012A7E8B90A21611835368",
            "to": "2547251642xx",
            "status": "accepted",
            "statusCode": "11",
            "keyword": "Omoka",
            "messagePart": 1,
            "type": "ondemand"
        }
    ]
}

Incoming keyword webhook

When a subscriber texts your keyword to your premium shortcode, Sozuri pushes this webhook to your application. Capture the linkId — you must include it on your reply so the carrier knows to charge the subscriber.

{
    "project": "yourproject_name",
    "shortcode": "25145",
    "keyword": "JOIN",
    "number": "2547251xxxxx",
    "network": "safaricom",
    "type": "linkNotification",
    "linkId": "256e487h2",
    "status": "success",
    "timestamp": "1603713484"
}

Delivery status webhook

Sozuri sends a delivery callback when the carrier confirms (or rejects) your premium message:

{
    "project": "yourproject_name",
    "shortcode": "25145",
    "keyword": "JOIN",
    "number": "2547251xxxxx",
    "network": "safaricom",
    "type": "premiumDelivery",
    "status": "success",
    "timestamp": "1603713484"
}

Error responses

On-demand 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
Keyword/shortcode pair doesn’t match an active premium service on this project. 400
{
    "status": "error",
    "description": "Unknown, Expired, or Inactive Premium Service"
}
The linkId on a paid reply doesn’t match an incoming-keyword event we issued. 400
{
    "status": "error",
    "description": "wrong link id"
}
Offer reference not found (e.g. you sent an offer_code that’s not configured). 400
{
    "status": "error",
    "statusCode": 1,
    "description": "Offer not found"
}
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

Where on-demand premium SMS earns its keep.

Sports scores & alerts

Subscriber texts GOAL to get the latest score on demand — charge per request, no app required.

23546
SportsZone
GOAL 20:14
Man City 2-1 Arsenal (78'). Haaland scored from a penalty. Send GOAL for next update. 20:14

News & horoscopes

Daily snippets of paid content on demand — the foundation of the original mobile content businesses.

23546
Daily Horoscope
LEO 07:01
Leo: Today brings unexpected good fortune in work matters. Trust your instincts. 07:01

Quizzes & trivia

Pay-per-question trivia campaigns on radio or TV — the keyword becomes the call-to-action.

🎯
23546
Drive-Time Trivia
Q3: Which country won the 2024 AFCON?
A - Nigeria
B - Cote d’Ivoire
C - South Africa 08:42
B 08:43
Correct! You’ve banked KES 200 in airtime. Next question at 09:00. Keep listening! 08:43

Monetise your content via SMS.

Apply for a premium shortcode and we&rsquo;ll handle billing, settlement and carrier paperwork end-to-end.