Send any WhatsApp Business message — text, rich media, locations, contacts, reactions and interactive buttons or lists — through the same Sozuri endpoint you use for SMS. One API, every conversation.

POST https://sozuri.net/api/v1/messaging
For compatibility with the WhatsApp Business platform, this endpoint uses snake_case field names instead of the camelCase used elsewhere in the API.

Request body shape

Every WhatsApp request shares the same wrapper. Set type to the content type you want to send and include the matching object (text, image, location, etc.):

Required headers
POST /api/v1/messaging
Content-Type: application/json
Authorization: Bearer Your_Project_API_KEY
Common request envelope
{
    "project": "YOUR_PROJECT_NAME",
    "from": "WHATSAPP_BUSINESS_NUMBER",
    "to": "TO_PHONE_NUMBER",
    "campaign": "YOUR_CAMPAIGN_NAME",
    "channel": "whatsapp",
    "recipient_type": "individual",
    "type": "TYPE",

    // include exactly ONE of these, depending on type
    "text":        { },
    "reaction":    { },
    "image":       { },
    "location":    { },
    "contacts":    [ ],
    "interactive": { }
}
FieldRequiredTypeDescription
projectYesStringThe Sozuri project that owns the API key making this request.
fromYesStringYour WhatsApp Business number, in E.164 format.
toYesStringA comma-separated list of recipient numbers in E.164. Sozuri will normalise 0722-503-129 to 254722503129.
channelYesStringAlways whatsapp on this endpoint.
recipient_typeYesStringAlways individual.
typeYesStringOne of text, reaction, image, video, audio, document, sticker, location, contacts, interactive.
campaignNoStringOptional label for reporting and analytics.
text / reaction / image / video / audio / document / sticker / location / contacts / interactiveOne of theseObjectThe content payload — one matches the type you chose. See each sample below.
apiKeyStringYour project API key. Recommended: send as a Bearer token in the Authorization header instead.

Response shape

Every WhatsApp request returns the same synchronous JSON envelope — one entry per recipient:

{
    "messageData": {
        "messages": 1
    },
    "recipients": [
        {
            "message_id": "f659b9ba4d9551c39ca61498126da29f68a1c1e9",
            "to": "+254725164293",
            "status": "queued"
        }
    ]
}
FieldTypeDescription
messageData.messagesNumberTotal messages accepted for delivery.
recipients[].message_idStringWhatsApp’s unique ID for the message. Use this to correlate delivery and read callbacks.
recipients[].toStringThe recipient’s phone number.
recipients[].statusStringInitial acceptance status (queued, accepted, unknown_number…). Final delivery status arrives via webhook.
All message types except reactions can be sent as a reply to a previous message — see replies at the bottom. WhatsApp will render the original message as a contextual bubble above the reply.

Text message

The most common message type — up to 4,096 characters of plain (or richly formatted) text. Optionally enable URL previews.

WhatsApp text message preview
curl -X POST 'https://sozuri.net/api/v1/messaging' \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "project": "YOUR_PROJECT_NAME",
    "from": "BUSINESS_PHONE_NUMBER",
    "channel": "whatsapp",
    "recipient_type": "individual",
    "campaign": "YOUR_CAMPAIGN_NAME",
    "to": "PHONE_NUMBER",
    "type": "text",
    "text": {
        "preview_url": false,
        "body": "MESSAGE_CONTENT"
    }
}'

Reaction

React to a customer’s previous message with an emoji — great for lightweight acknowledgements (“got it”, “thanks”, “loved that photo”).

WhatsApp reaction preview
curl -X POST 'https://sozuri.net/api/v1/messaging' \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "project": "YOUR_PROJECT_NAME",
    "from": "BUSINESS_PHONE_NUMBER",
    "channel": "whatsapp",
    "recipient_type": "individual",
    "campaign": "YOUR_CAMPAIGN_NAME",
    "to": "PHONE_NUMBER",
    "type": "reaction",
    "reaction": {
        "message_id": "MESSAGE_ID",
        "emoji": "๐Ÿ˜€"
    }
}'

Media messages

Send an image, video, audio, document or sticker by setting type to the media kind and providing a link to a publicly accessible file.

The media URL must be reachable from the public internet. WhatsApp downloads the file from your server before delivery — if the link is private, the message will fail.
WhatsApp media message preview
curl -X POST 'https://sozuri.net/api/v1/messaging' \
  -H 'Authorization: Bearer apiKey' \
  -H 'Content-Type: application/json' \
  -d '{
    "project": "YOUR_PROJECT_NAME",
    "from": "BUSINESS_PHONE_NUMBER",
    "channel": "whatsapp",
    "recipient_type": "individual",
    "campaign": "YOUR_CAMPAIGN_NAME",
    "to": "PHONE_NUMBER",
    "type": "image",
    "image": {
        "link": "https://IMAGE_URL"
    }
}'

Location

Send a pinned location with optional name and address — perfect for “here’s our shop”, “your delivery driver is here”, or sharing a meeting point.

WhatsApp location message preview
curl -X POST 'https://sozuri.net/api/v1/messaging' \
  -H 'Authorization: Bearer apiKey' \
  -H 'Content-Type: application/json' \
  -d '{
    "project": "YOUR_PROJECT_NAME",
    "from": "BUSINESS_PHONE_NUMBER",
    "channel": "whatsapp",
    "recipient_type": "individual",
    "campaign": "YOUR_CAMPAIGN_NAME",
    "to": "PHONE_NUMBER",
    "type": "location",
    "location": {
        "longitude": LONG_NUMBER,
        "latitude": LAT_NUMBER,
        "name": "LOCATION_NAME",
        "address": "LOCATION_ADDRESS"
    }
}'

Contact card

Share one or more contact cards — the recipient can save the contact straight to their phone with a tap. Useful for support escalations, referrals, or sharing a sales rep’s details.

WhatsApp contact card preview
curl -X POST 'https://sozuri.net/api/v1/messaging' \
  -H 'Authorization: Bearer apiKey' \
  -H 'Content-Type: application/json' \
  -d '{
    "project": "YOUR_PROJECT_NAME",
    "from": "BUSINESS_PHONE_NUMBER",
    "channel": "whatsapp",
    "recipient_type": "individual",
    "campaign": "YOUR_CAMPAIGN_NAME",
    "to": "PHONE_NUMBER",
    "type": "contacts",
    "contacts": [{
        "addresses": [
            { "street": "STREET", "city": "CITY", "state": "STATE", "zip": "ZIP", "country": "COUNTRY", "country_code": "COUNTRY_CODE", "type": "HOME" },
            { "street": "STREET", "city": "CITY", "state": "STATE", "zip": "ZIP", "country": "COUNTRY", "country_code": "COUNTRY_CODE", "type": "WORK" }
        ],
        "birthday": "YEAR_MONTH_DAY",
        "emails": [
            { "email": "EMAIL", "type": "WORK" },
            { "email": "EMAIL", "type": "HOME" }
        ],
        "name": {
            "formatted_name": "NAME",
            "first_name": "FIRST_NAME",
            "last_name": "LAST_NAME",
            "middle_name": "MIDDLE_NAME",
            "suffix": "SUFFIX",
            "prefix": "PREFIX"
        },
        "org": {
            "company": "COMPANY",
            "department": "DEPARTMENT",
            "title": "TITLE"
        },
        "phones": [
            { "phone": "PHONE_NUMBER", "type": "HOME" },
            { "phone": "PHONE_NUMBER", "type": "WORK", "wa_id": "PHONE_OR_WA_ID" }
        ],
        "urls": [
            { "url": "URL", "type": "WORK" },
            { "url": "URL", "type": "HOME" }
        ]
    }]
}'

Interactive: lists & buttons

Interactive messages let customers tap their reply instead of typing it. There are two flavours:

  • List messages — up to 10 selectable rows grouped into sections. Best for menus, catalogues and structured choices.
  • Reply buttons — up to 3 quick-reply buttons. Best for yes/no, confirm/cancel and binary choices.
WhatsApp interactive chatbot preview
List message
curl -X POST 'https://sozuri.net/api/v1/messaging' \
  -H 'Authorization: Bearer apiKey' \
  -H 'Content-Type: application/json' \
  -d '{
    "project": "YOUR_PROJECT_NAME",
    "from": "BUSINESS_PHONE_NUMBER",
    "channel": "whatsapp",
    "recipient_type": "individual",
    "campaign": "YOUR_CAMPAIGN_NAME",
    "to": "PHONE_NUMBER",
    "type": "interactive",
    "interactive": {
        "type": "list",
        "header": { "type": "text", "text": "HEADER_TEXT" },
        "body":   { "text": "BODY_TEXT" },
        "footer": { "text": "FOOTER_TEXT" },
        "action": {
            "button": "BUTTON_TEXT",
            "sections": [
                {
                    "title": "SECTION_1_TITLE",
                    "rows": [
                        { "id": "SECTION_1_ROW_1_ID", "title": "SECTION_1_ROW_1_TITLE", "description": "SECTION_1_ROW_1_DESCRIPTION" },
                        { "id": "SECTION_1_ROW_2_ID", "title": "SECTION_1_ROW_2_TITLE", "description": "SECTION_1_ROW_2_DESCRIPTION" }
                    ]
                },
                {
                    "title": "SECTION_2_TITLE",
                    "rows": [
                        { "id": "SECTION_2_ROW_1_ID", "title": "SECTION_2_ROW_1_TITLE", "description": "SECTION_2_ROW_1_DESCRIPTION" },
                        { "id": "SECTION_2_ROW_2_ID", "title": "SECTION_2_ROW_2_TITLE", "description": "SECTION_2_ROW_2_DESCRIPTION" }
                    ]
                }
            ]
        }
    }
}'
Reply buttons
curl -X POST 'https://sozuri.net/api/v1/messaging' \
  -H 'Authorization: Bearer apiKey' \
  -H 'Content-Type: application/json' \
  -d '{
    "project": "YOUR_PROJECT_NAME",
    "from": "BUSINESS_PHONE_NUMBER",
    "channel": "whatsapp",
    "recipient_type": "individual",
    "campaign": "YOUR_CAMPAIGN_NAME",
    "to": "PHONE_NUMBER",
    "type": "interactive",
    "interactive": {
        "type": "button",
        "body": { "text": "BUTTON_TEXT" },
        "action": {
            "buttons": [
                { "type": "reply", "reply": { "id": "UNIQUE_BUTTON_ID_1", "title": "BUTTON_TITLE_1" } },
                { "type": "reply", "reply": { "id": "UNIQUE_BUTTON_ID_2", "title": "BUTTON_TITLE_2" } }
            ]
        }
    }
}'

Reply to a previous message

To quote an earlier message in the conversation, add a context object with the original message_id. WhatsApp will render the original above your new message as a contextual bubble.

WhatsApp reply preview
curl -X POST 'https://sozuri.net/api/v1/messaging' \
  -H 'Authorization: Bearer apiKey' \
  -H 'Content-Type: application/json' \
  -d '{
    "project": "YOUR_PROJECT_NAME",
    "from": "BUSINESS_PHONE_NUMBER",
    "channel": "whatsapp",
    "campaign": "YOUR_CAMPAIGN_NAME",
    "context": {
        "message_id": "MESSAGE_ID"
    },
    "to": "PHONE_NUMBER",
    "type": "text",
    "text": {
        "preview_url": false,
        "body": "your-text-message-content"
    }
}'

Error responses

The WhatsApp endpoint uses several error envelope shapes depending on where the failure occurs. Auth errors (Unknown project.) follow the SMS envelope and are documented on the Authentication page.

ConditionHTTPResponse body
Project credit balance is too low to send the message. 400
{
    "MessageData": {
        "Error": "Insufficient balance. Top up and try again."
    }
}
The sending business from number isn’t configured on any WhatsApp account in this project. 400
{ "error": "Whatsapp Number could not be found" }
The project has no resolvable WhatsApp Business Account (WABA) link. 400
{ "error": "Whatsapp Account could not be found" }
The context.message_id on a reply (or reaction.message_id on a reaction) doesn’t match a message in this project. 422
{
    "message": "Error",
    "errors": {
        "message_id": ["The provided message_id does not exist."]
    }
}
Sandbox sender: recipient hasn’t been registered as a sandbox test number. 422
{
    "message": "The given data was invalid",
    "errors": {
        "to": ["{from} is a Sandbox Whatsapp Business number which can only send messages to sandbox customer numbers. Add {to} as a sandbox number from your Sozuri project menu: Whatsapp > settings , to be able to use it for testing."]
    }
}
Database persistence failure after acceptance. 500
{
    "message": "Error",
    "errors": {
        "message": ["General failure. Contact support@sozuri.net for assistance"]
    }
}
WhatsApp’s asynchronous failures (Re-engagement message, template rejected, etc.) arrive on the delivery webhook, not the send response. See WhatsApp delivery webhook for the failure payload shape.

Use cases

The conversations WhatsApp powers for businesses across Kenya.

Conversational commerce

Send catalogues as interactive lists, accept orders via buttons, and confirm payment in a single thread.

G
Galaxion Bakery
business account
Hi, do you have chocolate cake today? 10:01
Yes! We have 1kg (KES 2,500) and 2kg (KES 4,500). Which would you like? 10:01
2kg please 10:02 โœ“โœ“
Great. Pay via Paybill 851900, account 4821. We deliver by 4pm. 10:02

Order tracking with a live map

Push a location pin when the rider sets off and update with a media message on delivery.

G
Glovo Kenya
business account
Your courier Brian is on the way! Live location below. 14:22
๐Ÿ“ Westlands Rd, Nairobi 14:22

Support & ticketing

Reply to a customer’s photo of a damaged item using the reply API, then escalate with a contact card for their support agent.

J
Jumia Support
business account
My package arrived damaged ๐Ÿ˜ž 11:32
So sorry to hear that, Wanjiru. I’m connecting you with our refund team now. 11:32
Agent: Brian Mwangi ยท +254 700 111 222 11:33

Surveys with interactive buttons

Replace plain-text Y/N replies with tappable buttons — lifts response rates and removes typos.

E
Equity Bank
business account
How did we do today, Wanjiru? Tap to rate your visit. 16:10
[ ๐Ÿ˜ Great ] [ ๐Ÿ˜ OK ] [ ๐Ÿ˜Ÿ Bad ] 16:10
๐Ÿ˜ Great 16:11 โœ“โœ“

Bring your business onto WhatsApp.

Get your business profile verified, connect your number, and start sending in days — we handle the Meta paperwork.