Sending messages

    6 min read
    ·
    422 views
    ·
    Updated 10/22/2026

    POST /v1/messages/send

    Send a text or media message through a connected channel.

    ℹ️ Sending is asynchronous: messages go into a queue and are sent within a few seconds. A successful response (202) means the message has been accepted for processing, not that it has already been delivered.

    URL

    POST https://api.wazzabee.com/api-gateway/v1/messages/send

    Headers

    Authorization: Bearer YOUR_API_KEY
    Content-Type: application/json

    Request body parameters

    ParameterTypeRequiredDescription
    channelIdstring (UUID)✅ YesChannel ID. Get it through GET /v1/channels
    chatIdstring✅ YesRecipient identifier: a phone number (for WhatsApp) or a chat_id (for Telegram)
    textstring✅*Message text. Required if mediaUrl is not set
    mediaUrlstring (URL)✅*Direct link to a media file (image, video, document). Required if text is not set
    mediaTypestringConditionalMedia type: photo, video, document, audio. Required whenever mediaUrl is set
    captionstringNoCaption for the media file. Works only together with mediaUrl
    senderNamestringNoAuthor name: who sent the message. Your agents see it in the WazzaBee chat and it comes back in the webhook. It is not passed on to the customer's messenger
    userIdstringNoThe employee's identifier in your CRM. We return it as is: there is no need to create that employee in WazzaBee
    automatedbooleanNotrue: the message was sent by a robot, an auto-reply or a reminder. Such a message is marked as automated in the chat
    campaignIdstringNoYour campaign label, up to 100 characters. It is returned in the response and in the outgoing, status and button click webhooks. You can filter GET /v1/messages by it and export sends in the dashboard: «Connectors» → «API» → «Export of API sends»

    * You need to set either text or mediaUrl, at least one of the two.

    Who sent the message

    By default a message sent through the API is signed in the chat simply as "via API", with no name. If your CRM knows the author, pass it along: the message will show "via API · Nazerke A." underneath, and the name will come back to you in the messages_outgoing webhook. That way the chat feed makes it clear which agent replied to the customer.

    curl -X POST "https://api.wazzabee.com/api-gateway/v1/messages/send" \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "channelId": "550e8400-e29b-41d4-a716-446655440000",
        "chatId": "77001234567",
        "text": "Hello! Your documents are ready.",
        "senderName": "Nazerke Akhmetova",
        "userId": "manager-42"
      }'

    Instead of senderName and userId you can pass an author object, the result is the same:

    {
      "channelId": "550e8400-e29b-41d4-a716-446655440000",
      "chatId": "77001234567",
      "text": "Hello!",
      "author": { "id": "manager-42", "name": "Nazerke Akhmetova" }
    }

    Mark messages that are not sent by a person (robots, auto-replies, reminders) with "automated": true. In the chat they will be shown separately from agent replies.

    ℹ️ The signature is visible only to you. The author's name is shown to your agents in the WazzaBee chat and comes through in webhooks. It is not passed on to the customer in WhatsApp or Telegram: they only see the message text.

    chatId format

    Channel typechatId formatExample
    WhatsApp (QR)Phone number with country code, no +77001234567
    WhatsApp (WABA)Phone number with country code, no +77001234567
    Telegram BotThe user's numeric chat_id123456789
    Telegram PersonalNumeric chat_id or username123456789

    Request examples

    Text message

    curl -X POST "https://api.wazzabee.com/api-gateway/v1/messages/send" \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "channelId": "550e8400-e29b-41d4-a716-446655440000",
        "chatId": "77001234567",
        "text": "Hello! Your order #1234 is ready for pickup."
      }'

    Image with a caption

    curl -X POST "https://api.wazzabee.com/api-gateway/v1/messages/send" \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "channelId": "550e8400-e29b-41d4-a716-446655440000",
        "chatId": "77001234567",
        "mediaUrl": "https://example.com/photo.jpg",
        "mediaType": "photo",
        "caption": "A photo of your order"
      }'

    Document

    curl -X POST "https://api.wazzabee.com/api-gateway/v1/messages/send" \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "channelId": "550e8400-e29b-41d4-a716-446655440000",
        "chatId": "77001234567",
        "mediaUrl": "https://example.com/invoice.pdf",
        "mediaType": "document"
      }'

    Successful response (202 Accepted)

    {
      "success": true,
      "queued": true,
      "queueId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "message": "The message has been queued for sending"
    }
    FieldTypeDescription
    successbooleanAlways true on success
    queuedbooleanThe message has been accepted into the queue
    queueIdstring (UUID)Unique ID in the sending queue. The same queueId comes in the delivery status webhook (messages_status) and in GET /v1/messages: use it to find out whether the message was delivered
    campaignIdstring | nullCampaign label, if you passed one
    messagestringA text description of the result

    Possible errors

    CodeErrorReason
    400Invalid JSON in the request bodyThe request body is not valid JSON
    400The channelId field is requiredThe channelId parameter was not passed
    400The chatId field is requiredThe chatId parameter was not passed
    400You must set text or mediaUrlNeither a text nor a media file was passed
    400The channel is inactiveThe channel is disabled or not set up
    400Unsupported channel typeThis channel type is not supported by the API
    403The channel is not linked to this integrationThe channel is not among those allowed for this API key
    404Channel not found or no accessThe channel does not exist or belongs to another user

    How it works under the hood

    1. The API checks authorization and access to the channel
    2. It looks for the contact by chatId (phone or external_id). If there is none, it creates a new one
    3. It looks for an existing conversation. If there is none, it creates a new one
    4. It picks the delivery method based on the channel type
    5. It puts the message into the message_queue
    6. A background process takes the message out of the queue and sends it through the channel