> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ycloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Send a WhatsApp message

> Send WhatsApp template, session, and media messages with the queued or synchronous API.

## What it is

The WhatsApp Messages API sends template, text, image, video, audio, document,
sticker, location, interactive, contact, and reaction messages from a connected
WhatsApp business phone number.

## Before you begin

* Store your YCloud API key in `YCLOUD_API_KEY`.
* Connect a WhatsApp Business Account and phone number to YCloud.
* Collect the sender phone number in E.164 format and either the recipient phone
  number, BSUID, or parent BSUID.
* Use an `APPROVED` template for ordinary template sends.
* Upload media first when the message references a YCloud media ID.

## How it works

Choose the endpoint based on when YCloud should submit the message to the
WhatsApp Business API.

| Endpoint | Behavior | Use it for |
| - | - | - |
| `POST /whatsapp/messages` | Queues the message and submits it asynchronously. | Most outbound messaging workflows. |
| `POST /whatsapp/messages/sendDirectly` | Submits the message synchronously to the WhatsApp Business API. | OTP and other time-sensitive messages. |

Both endpoints return a YCloud message object. The initial response does not
confirm final delivery. Later status changes arrive through
`whatsapp.message.updated` Webhooks.

## Direct Send for utility content

Direct Send can submit eligible utility content or convert an existing utility
template. It works with either sending endpoint. The `sendDirectly` endpoint
controls synchronous submission; it does not enable Direct Send by itself.

Follow [Direct Send best practices](/en/api-reference/guides/whatsapp-platform/best-practices/direct-send)
for eligibility, requests, template conversion, limits, and account events.

## Choose the best send time

Match the send time to the message purpose and the recipient's local time.

* Send OTPs and other time-sensitive messages immediately. Use
  `POST /whatsapp/messages/sendDirectly` when your workflow needs the submission
  result before continuing.
* Send transactional updates when the related event occurs, such as a payment,
  shipment, or appointment change.
* Schedule marketing messages for reasonable hours in the recipient's time zone.
  Use your own delivery, read, and conversion data to test different time slots
  for each audience instead of assuming one universal best hour.
* Start a scheduled campaign with a small recipient group. Check delivery,
  response, and opt-out results before sending to the rest of the audience.
* Avoid repeated sends when a message is delayed. Store `externalId` and process
  `whatsapp.message.updated` Webhooks before deciding whether to retry.

## Request

Choose either endpoint above, then use the request body that matches the message
type. The `from` value is your connected WhatsApp business phone number. Address
the recipient with `to` in E.164 format or with `recipient` set to a BSUID or
parent BSUID.

### Common request fields

| Field | Required | Description |
| - | - | - |
| `from` | Yes | Connected WhatsApp business phone number in E.164 format. |
| `to` | Conditional | Recipient phone number in E.164 format. Required when `recipient` is absent. |
| `recipient` | Conditional | Recipient BSUID or parent BSUID. Required when `to` is absent. |
| `type` | Yes | Message type. Include the content field that matches this value. |
| `template`, `text`, `image`, and other type fields | Conditional | Content object required by the selected `type`. |
| `context` | No | Message context used when replying to an earlier message. |
| `externalId` | No | Your unique reference for reconciling the message with an internal record. |
| `filterUnsubscribed` | No | Enqueue only. Defaults to `false`; when `true`, filters recipients on the unsubscribe list. |
| `filterBlocked` | No | Enqueue only. Defaults to `false`; when `true`, filters blocked recipients. |

<Warning>
  `filterUnsubscribed` and `filterBlocked` apply only to
  `POST /whatsapp/messages`; they do not apply to `sendDirectly`. A filtered
  queued message fails with `RECIPIENT_UNSUBSCRIBED` or
  `RECIPIENT_IN_BLOCK_LIST` in its status webhook. For synchronous sends,
  enforce consent, unsubscribe, and block checks in your application.
</Warning>

Provide at least one of `to` or `recipient`. If you include both, YCloud uses
`to` and ignores `recipient`.

<Note>
  One-tap, zero-tap, and copy-code authentication templates require a phone
  number. Use `to` for these template types.
</Note>

### Request examples

<AccordionGroup>
  <Accordion title="Template message">
    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "from": "+16315551111",
      "to": "+16315551111",
      "type": "template",
      "template": {
        "name": "sample_whatsapp_template",
        "language": {
          "code": "en",
          "policy": "deterministic"
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="Text message">
    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "from": "+16315551111",
      "to": "+16315551111",
      "type": "text",
      "text": {
        "body": "Hello from YCloud!"
      }
    }
    ```
  </Accordion>

  <Accordion title="Image message">
    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "from": "+16315551111",
      "to": "+16315551111",
      "type": "image",
      "image": {
        "id": "MEDIA_ID",
        "caption": "Product image"
      }
    }
    ```
  </Accordion>

  <Accordion title="Video message">
    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "from": "+16315551111",
      "to": "+16315551111",
      "type": "video",
      "video": {
        "id": "MEDIA_ID",
        "caption": "Product video"
      }
    }
    ```
  </Accordion>

  <Accordion title="Audio message">
    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "from": "+16315551111",
      "to": "+16315551111",
      "type": "audio",
      "audio": {
        "id": "MEDIA_ID"
      }
    }
    ```
  </Accordion>

  <Accordion title="Document message">
    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "from": "+16315551111",
      "to": "+16315551111",
      "type": "document",
      "document": {
        "id": "MEDIA_ID",
        "filename": "invoice.pdf"
      }
    }
    ```
  </Accordion>

  <Accordion title="Sticker message">
    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "from": "+16315551111",
      "to": "+16315551111",
      "type": "sticker",
      "sticker": {
        "id": "MEDIA_ID"
      }
    }
    ```
  </Accordion>

  <Accordion title="Location message">
    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "from": "+16315551111",
      "to": "+16315551111",
      "type": "location",
      "location": {
        "latitude": 37.422,
        "longitude": -122.084,
        "name": "Googleplex",
        "address": "1600 Amphitheatre Pkwy, Mountain View, CA"
      }
    }
    ```
  </Accordion>

  <Accordion title="Interactive message">
    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "from": "+16315551111",
      "to": "+16315551111",
      "type": "interactive",
      "interactive": {
        "type": "button",
        "body": {
          "text": "Do you want to continue?"
        },
        "action": {
          "buttons": [
            {
              "type": "reply",
              "reply": {
                "id": "yes",
                "title": "Yes"
              }
            }
          ]
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="Contacts message">
    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "from": "+16315551111",
      "to": "+16315551111",
      "type": "contacts",
      "contacts": [
        {
          "name": {
            "formatted_name": "John Smith"
          },
          "phones": [
            {
              "phone": "+16315551111",
              "type": "CELL"
            }
          ]
        }
      ]
    }
    ```
  </Accordion>

  <Accordion title="Reaction message">
    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "from": "+16315551111",
      "to": "+16315551111",
      "type": "reaction",
      "reaction": {
        "message_id": "wamid.BgNODYxN...",
        "emoji": "👍"
      }
    }
    ```
  </Accordion>
</AccordionGroup>

## Response

A successful response returns the YCloud message object. An initial
`status: accepted` means YCloud accepted the send request. It does not mean the
message has been sent by Meta or delivered to the WhatsApp user.

### Example response

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "id": "MESSAGE_ID",
  "wabaId": "WHATSAPP_BUSINESS_ACCOUNT_ID",
  "from": "+16315551111",
  "to": "+16315552222",
  "type": "text",
  "status": "accepted",
  "externalId": "order-10001",
  "createTime": "2026-07-16T12:00:00.000Z"
}
```

### Response fields

| Field | Description |
| - | - |
| `id` | YCloud message ID. Store it for retrieval and Webhook correlation. |
| `wamid` | Original WhatsApp message ID. Available after submission to WhatsApp. |
| `wabaId` | WhatsApp Business Account ID. |
| `from`, `to` | Sender and recipient phone numbers. |
| `type` | Message content type. |
| `status` | Current state, such as `accepted`, `sent`, `failed`, `delivered`, or `read`. |
| `errorCode`, `errorMessage` | YCloud failure details when `status` is `failed`. |
| `whatsappApiError` | Error returned by the WhatsApp Business API when available. |
| `externalId` | The reference supplied in the request. |
| `category` | Direct Send category, such as `utility` for the utility examples above. |
| `ttlSeconds` | Direct Send message lifetime, when set on the message. |
| `totalPrice`, `currency` | Estimated or final message price and currency. |
| `createTime`, `sendTime`, `deliverTime`, `readTime` | Lifecycle timestamps in RFC 3339 format. |

## Delivery status

Subscribe to `whatsapp.message.updated` Webhooks to receive later status changes
such as `sent`, `failed`, `delivered`, or `read`.

Use `GET /whatsapp/messages/{id}` when you need to retrieve a message directly.

<Tip>
  For media messages, upload the file first with `POST /whatsapp/media/{phoneNumber}/upload`, then use the returned media ID in the message payload.
</Tip>

## Limits and troubleshooting

* Ordinary template sends require an `APPROVED` template; `ARCHIVED` templates
  cannot be sent as ordinary template messages.
* Do not retry an accepted request without an idempotency strategy. A repeated
  request can send a duplicate message.
* Use the YCloud `id`, `wamid`, `externalId`, and Webhook status when
  investigating delivery.
* Inspect `whatsappApiError` when a direct request reaches Meta and Meta rejects
  it.

For throughput limits, see [Rate limits](/en/api-reference/guides/api-fundamentals/rate-limits).

<Card title="Direct Send best practices" icon="bolt" href="/en/api-reference/guides/whatsapp-platform/best-practices/direct-send">
  Send utility content, convert templates, and monitor category and restriction events.
</Card>

<Card title="Production best practices" icon="shield-check" href="/en/api-reference/guides/whatsapp-platform/whatsapp-messages-api-best-practices">
  Design status synchronization, bounded retries, consent checks, media reuse,
  and throughput controls for a production integration.
</Card>

<Card title="Use business-scoped user IDs" icon="user-tag" href="/en/api-reference/guides/whatsapp-platform/use-business-scoped-user-ids">
  Send messages and calls by BSUID, request phone numbers, manage Meta contact
  book entries, and process BSUID webhook fields.
</Card>

## Complete integration examples

For the full template-creation and variable-binding workflow, see
[Template creation examples](/en/api-reference/guides/examples/api-examples/whatsapp-template-creation-examples)
and [Messaging examples](/en/api-reference/guides/examples/api-examples/whatsapp-messaging-examples).
Use [WhatsApp error handling](/en/api-reference/guides/whatsapp-platform/handle-whatsapp-errors)
to distinguish request rejection from later delivery failures, and
[Webhook receiver implementation](/en/api-reference/guides/api-fundamentals/implement-a-webhook-receiver)
to verify signatures and accept status updates durably.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.