Skip to content
All posts

Technical

How to send a message with the WhatsApp API

August 12, 2026 · 7 min read

Sending a WhatsApp message through the API is one HTTP POST. The parts that trip people up are which message type you are allowed to send, and the difference between a phone number and a phone number ID.

This assumes you already have a WhatsApp Business Account, a phone number registered on the Cloud API, and an access token. If you do not, start with what the WhatsApp API is.

What you need

  • Phone number ID. Not the phone number itself. It is a numeric ID from the WhatsApp section of your Meta app dashboard.
  • Access token. Temporary tokens from the dashboard expire in 24 hours. Use a permanent System User token for anything real.
  • Recipient number in international format, digits only, country code included, no plus sign and no spaces. An Indian number looks like 919876543210.

Sending a template message

To start a conversation you must send an approved template. This is the request you will use most.

curl -X POST \
  "https://graph.facebook.com/v21.0/<PHONE_NUMBER_ID>/messages" \
  -H "Authorization: Bearer <ACCESS_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "messaging_product": "whatsapp",
    "to": "919876543210",
    "type": "template",
    "template": {
      "name": "order_shipped",
      "language": { "code": "en" },
      "components": [
        {
          "type": "body",
          "parameters": [
            { "type": "text", "text": "Priya" },
            { "type": "text", "text": "BA-10428" }
          ]
        }
      ]
    }
  }'

The parameters array fills the template placeholders in order, so the first entry is {{1}} and the second is {{2}}. A mismatch between the number of parameters and the number of placeholders is the most common failure here.

Sending a free-form message

Once a customer has messaged you, a 24-hour service window opens and you can reply with plain text, no template needed.

curl -X POST \
  "https://graph.facebook.com/v21.0/<PHONE_NUMBER_ID>/messages" \
  -H "Authorization: Bearer <ACCESS_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "messaging_product": "whatsapp",
    "to": "919876543210",
    "type": "text",
    "text": { "body": "Your order is out for delivery today." }
  }'

Send this outside the 24-hour window and it fails. That is not a bug, it is the rule the whole platform is built around.

What comes back

{
  "messaging_product": "whatsapp",
  "contacts": [{ "input": "919876543210", "wa_id": "919876543210" }],
  "messages": [{ "id": "wamid.HBgMOTE5..." }]
}

A 200 means Meta accepted the message, not that it was delivered. Delivery and read receipts arrive later on your webhook, keyed by that wamid. Store it. Setting that up is covered in our webhook guide.

Errors you will hit first

  • 131030 in development: the recipient is not in your allowed list. Test numbers must be added to the app until it goes live.
  • 131047: the 24-hour window has closed. Send a template instead.
  • 132001: the template does not exist, or the language code does not match the approved one. en and en_US are different templates.
  • 190: the access token expired. This is the temporary token biting you.

There is a fuller list with fixes in our WhatsApp API error codes reference.

Before you build this yourself

Sending one message is easy. What takes the time is everything after: template submission and versioning, webhook handling and retries, media uploads, per-number rate limits, a shared inbox so your team can answer, and the reporting to know what happened.

If you want the API without building that layer, that is what Boldally Chat is, and Meta’s rates pass through at cost. If you would rather build it, the webhook guide is the next thing to read.

Put your WhatsApp to work.

Free for 14 days. No credit card, and no setup call to sit through.