Send messages

Learn how to send messages on WhatsApp using Unipile API.

There is two scenarios where you want to send messages:

  • You don't have yet a conversation with the recipient(s), so you create a new chat and send the first message using Start a Chat.
  • You already have a conversation with the recipient(s), so you send a message in an existing chat using Send a Message.

❗️

Spam detection

If you initiate too many new conversations without receiving responses or if there are a high number of signals of spam/block, it may temporarily restrict your account.

Incorporate realistic delays between messages to mimic human behavior. Avoid sending messages with intervals shorter than 10-20 seconds to align with natural conversation patterns.


Start a new conversation

Find User IDs

For a new WhatsApp recipient known only by phone number, user IDs follow this convenient format:

  1. Include the full international number (with country code).
  2. Remove any spaces, + signs, or formatting characters.
  3. Append @s.whatsapp.net to the end.

For example:
+33 44 55 66 77 88 → [email protected]

If the recipient comes from a previous Unipile response, reuse its id exactly as returned. Depending on the WhatsApp account and conversation, this ID may end in @lid instead of @s.whatsapp.net; both forms are accepted by Unipile.


Check whether a phone number uses WhatsApp

Use Get a User Profile with the phone-number user ID described above. The response tells you whether that phone number belongs to a WhatsApp user:

  • 200 OK: the user exists and the response contains their profile.
  • 404 Not Found: no WhatsApp user exists for that phone number.
const { data: profile } = await usersApi.getUserProfile({
  path: {
    account_id: "acc_123456789",
    user_id: "[email protected]",
  },
});
profile = users_api.get_user_profile(
    "[email protected]",
    "acc_123456789",
)
curl --request GET \
     --url 'https://api.unipile.com/v2/acc_123456789/users/[email protected]' \
     --header 'accept: application/json' \
     --header 'X-API-KEY: your-api-key'

Use this lookup when you need to validate a recipient before starting a conversation.


Start an individual chat

To initiate a conversation with another user, use the Start a Chat method and provide the recipient’s User ID.

WhatsApp allows only one individual chat per user. Attempting to start a chat with a user who already has an existing conversation will simply send a message in that existing chat.

const { data, error } = await messagingApi.startChat({
  path: {
    account_id: "acc_123456789",
  },
  body: {
    user_ids: ["[email protected]"],
    text: "This is the first message in the chat",
  },
});
chat = messaging_api.start_chat(
    "acc_123456789",
    {
        "user_ids": ["[email protected]"],
        "text": "This is the first message in the chat",
    },
)
📘

Note about chat ids

You may notice that the chat_id returned in the response is the same as the recipient’s user ID.
This is expected behavior: for individual chats, WhatsApp uses the recipient’s ID as the chat identifier.


Start a group chat

To create a new group chat, use the Start a Chat endpoint and provide a list of members in user_ids.

The Unipile API performs two actions in one request:

  • It creates the group by inviting all members.
  • It sends the first message to the group.

If you want to create the group without sending a message, simply set the text field to an empty string.
You can then send a message later using the Send a Message method.

You may optionally specify a group name. If not provided, the group name will be automatically generated from the names of the initial members.

const { data, error } = await messagingApi.startChat({
  path: {
    account_id: "acc_123456789",
  },
  body: {
    user_ids: ["[email protected]", "[email protected]"],
    text: "This is the first message in the chat",
    name: "Group Chat Name",
  },
});
chat = messaging_api.start_chat(
    "acc_123456789",
    {
        "user_ids": [
            "[email protected]",
            "[email protected]",
        ],
        "text": "This is the first message in the chat",
        "name": "Group Chat Name",
    },
)

Send a message in a conversation

To send a message in an existing chat, use the Send a Message method and provide the ID of the Chat to send the message in. See Retrieve chats & messages to find chat IDs.

const { data, error } = await messagingApi.sendMessage({
  path: {
    account_id: "acc_123456789",
    chat_id: "chat_id",
  },
  body: {
    text: "Hello, world!",
  },
});
message = messaging_api.send_message(
    "chat_id",
    "acc_123456789",
    {"text": "Hello, world!"},
)
curl --request POST \
     --url https://api.unipile.com/v2/account_id/chats/chat_id/messages/send \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "text": "Hello, World!"
}
'

Format text messages

WhatsApp formatting feature is fully supported.


Send attachments

WhatsApp only allows a single attachment per message.

  • If you send multiple attachments in one API call, Unipile will automatically send them as separate messages, one per attachment.
  • Any text content provided in the request will be sent as an additional message after all the attachments.
  • If you want each attachment to have its own caption, you must call Send a Message once per attachment, including its caption in the text field.
❗

Provider limitations

WhatsApp enforces specific size and format restrictions for attachments. Refer to the WhatsApp Help Center for the latest limits.

The following examples use Send a Message but you can send attachments with Start a Chat as well.


Send Images & Videos

To send an image or video with an inline preview, call the Send a Message method and include files in the attachments array.

Any file with a MIME type starting with image/ or video/ will be sent as media with an inline preview in the chat.

const imageFile = await readFile('image.png');
const videoFile = await readFile('video.mp4');

const { data, error } = await messagingApi.sendMessage({
  path: {
    account_id: "acc_123456789",
    chat_id: "chat_id",
  },
  body: {
    text: '',
    attachments: [
      {
        content: imageFile.toString('base64'),
        content_type: 'image/png',
        filename: 'image.png',
      },
			{
        content: videoFile.toString('base64'),
        content_type: 'video/mp4',
        filename: 'video.mp4',
      },
    ],
  },
});
import base64

with open("image.png", "rb") as f:
    image_file = base64.b64encode(f.read()).decode("utf-8")
with open("video.mp4", "rb") as f:
    video_file = base64.b64encode(f.read()).decode("utf-8")

message = messaging_api.send_message(
    "chat_id",
    "acc_123456789",
    {
        "text": "",
        "attachments": [
            {
                "content": image_file,
                "content_type": "image/png",
                "filename": "image.png",
            },
            {
                "content": video_file,
                "content_type": "video/mp4",
                "filename": "video.mp4",
            },
        ],
    },
)
curl --request POST \
     --url https://api.unipile.com/v2/account_id/chats/chat_id/messages/send \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "attachments": [
    {
      "content": "base64",
      "content_type": "image/png",
      "filename": "image.png",
    },
    {
      "content": "base64",
      "content_type": "video/mp4",
      "filename": "video.mp4",
    }

  ]
}
'

Send Documents

To send a document, use the Send a Message method and provide the file as an attachment.

In the official WhatsApp apps, you can choose to send images or videos as documents (which appear without a preview).
Unipile does not support this mode — all images and videos are always sent as media with inline previews as mentioned in the previous section.

const file = await readFile('document.pdf');

const { data, error } = await messagingApi.sendMessage({
  path: {
    account_id: "acc_123456789",
    chat_id: "chat_id",
  },
  body: {
    text: '',
    attachments: [
      {
        content: file.toString('base64'),
        content_type: 'application/pdf',
        filename: 'document.pdf',
      },
    ],
  },
});
import base64

with open("document.pdf", "rb") as f:
    file = base64.b64encode(f.read()).decode("utf-8")

message = messaging_api.send_message(
    "chat_id",
    "acc_123456789",
    {
        "text": "",
        "attachments": [
            {
                "content": file,
                "content_type": "application/pdf",
                "filename": "document.pdf",
            }
        ],
    },
)
curl --request POST \
     --url https://api.unipile.com/v2/account_id/chats/chat_id/messages/send \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "attachments": [
    {
      "content": "base64",
      "content_type": "application/pdf",
      "filename": "document.pdf",
    }
  ]
}
'

Send a voice message

To send a voice message, call the Send a Message method and attach the audio file with the voice_note property set to true so the audio will appear in the chat as an inline, playable voice message.

const file = await readFile('voice.mp3');

const { data, error } = await messagingApi.sendMessage({
  path: {
    account_id: "acc_123456789",
    chat_id: "chat_id",
  },
  body: {
    text: '',
    attachments: [
      {
        content: file.toString('base64'),
        content_type: 'audio/mpeg',
        filename: 'voice.mp3',
        voice_note: true,
      },
    ],
  },
});
import base64

with open("voice.mp3", "rb") as f:
    file = base64.b64encode(f.read()).decode("utf-8")

message = messaging_api.send_message(
    "chat_id",
    "acc_123456789",
    {
        "text": "",
        "attachments": [
            {
                "content": file,
                "content_type": "audio/mpeg",
                "filename": "voice.mp3",
                "voice_note": True,
            }
        ],
    },
)
curl --request POST \
     --url https://api.unipile.com/v2/account_id/chats/chat_id/messages/send \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "attachments": [
    {
      "content": "base64",
      "content_type": "audio/mpeg",
      "filename": "voice.mp3",
      "voice_note": true
    }
  ]
}
'

Reply to a specific message

To send a message as a reply to a specific message (to see the replied message embedded), use the Send a Message method and provide the ID of the message to reply to as quote_id.

const { data, error } = await messagingApi.sendMessage({
  path: {
    account_id: "acc_123456789",
    chat_id: "chat_id",
  },
  body: {
    text: "This is a reply to a message",
    quote_id: "message_id",
  },
});
message = messaging_api.send_message(
    "chat_id",
    "acc_123456789",
    {
        "text": "This is a reply to a message",
        "quote_id": "message_id",
    },
)
curl --request POST \
     --url https://api.unipile.com/v2/account_id/chats/chat_id/messages/send \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "quote_id": "message_id",
  "text": "This is a reply to a message"
}
'

Forward a message to another Chat

To forward a message into another chat, use the Forward a Message method and provider the ID of the chat to forward the message to.

In WhatsApp, forwarded messages are not embedded into another one, but they are sent as a new message flagged as forwarded, so filling the text field has no effect.

const { data, error } = await messagingApi.forwardMessage({
  path: {
    account_id: "acc_123456789",
    chat_id: "chat_id",
    message_id: "message_id",
  },
  body: {
    chat_id: "destination_chat_id",
  },
});
messaging_api.forward_message(
    "chat_id",
    "message_id",
    "acc_123456789",
    {"chat_id": "destination_chat_id"},
)
curl --request POST \
     --url https://api.unipile.com/v2/account_id/chats/chat_id/messages/message_id/forward \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "chat_id": "destination_chat_id",
}
'

Be notified about read messages

To be notified when a sent message is read by someone in the conversations, Configure a webhook that listen for message.receipt.read events.



Did this page help you?