WhatsApp Business Platform

WhatsApp Cloud API explained: how messages, webhooks and templates fit together

How the WhatsApp Cloud API works: accounts, webhooks, access tokens, templates, the 24-hour window and message statuses, in plain language with examples.

By Stack Bridge Labs · · 3 min read

The WhatsApp Cloud API is Meta’s hosted interface to the WhatsApp Business Platform. It looks simple from the outside (send a message, receive a message), but a reliable integration depends on understanding a handful of concepts that the documentation spreads across many pages. This is the overview we wish every project started with.

The building blocks

  • Meta business portfolio. The business account everything hangs from. Business verification, where needed, happens here.
  • WhatsApp Business Account (WABA). Holds your phone numbers, message templates and billing.
  • Phone number. The number customers message. It is registered for the API and gets a display name that WhatsApp reviews.
  • Meta app. The developer app that owns the webhook and the credentials your software uses.
  • Access token. What your server presents on every API call. Production integrations use a long-lived token tied to a system user, never a personal login, and keep it on the server.

Receiving messages: the webhook

You give Meta an HTTPS address. When a customer writes to you, or when the status of a message you sent changes, Meta sends a POST request to that address. You subscribe to the “messages” field to receive both.

Two details matter more than any others. First, when you register the webhook Meta makes a one-time GET request containing a challenge, which you must echo back after checking a verify token you chose. Second, every later POST carries an X-Hub-Signature-256 header, an HMAC of the raw body made with your app secret. Verify it before you trust the payload.

Handling the webhook (pseudocode)
// GET: one-time verification
if (query["hub.mode"] === "subscribe" && query["hub.verify_token"] === VERIFY_TOKEN)
  return reply(200, query["hub.challenge"]);

// POST: verify, acknowledge, process later
const expected = "sha256=" + hmacSha256(APP_SECRET, rawBody);
if (!timingSafeEqual(expected, headers["x-hub-signature-256"])) return reply(401);
reply(200);
queue.add("whatsapp.event", JSON.parse(rawBody));

Answer quickly and do the work afterwards. If your endpoint is slow or fails, Meta retries, which means the same message can arrive more than once. Every incoming message has a unique ID: record it, and ignore any you have already handled.

What an incoming message looks like

The payload nests the useful part several levels down: entry[].changes[].value. Inside value, the messages array holds what the customer sent (text, an image, a location, a tap on a button) and contacts holds their WhatsApp ID and profile name. The metadata.phone_number_id tells you which of your numbers was contacted, which matters as soon as you have more than one.

Sending messages

You send by POSTing JSON to the Graph API endpoint for your phone number, with your token in the Authorization header. The type decides the rest: plain text, media, a location, an interactive message with reply buttons or a list, or a template.

Sending a template message (simplified)
POST https://graph.facebook.com/<API_VERSION>/<PHONE_NUMBER_ID>/messages
Authorization: Bearer <ACCESS_TOKEN>

{
  "messaging_product": "whatsapp",
  "to": "91…",
  "type": "template",
  "template": {
    "name": "token_confirmed",
    "language": { "code": "en" },
    "components": [{ "type": "body", "parameters": [
      { "type": "text", "text": "A-104" },
      { "type": "text", "text": "Central Branch" }
    ]}]
  }
}

The 24-hour window and templates

When a customer messages you, a 24-hour customer service window opens. Inside it you can reply with any free-form message. Once it closes, you can only send template messages: pre-written messages, with variables, that WhatsApp has reviewed and approved. Templates are also how a business starts a conversation. Message templates are explained in more detail here.

Delivery statuses

Each message you send returns a message ID. Afterwards, status events arrive at the same webhook: sent, delivered, read, or failed. A failure carries an error describing why, for example that the number is not on WhatsApp or that the customer has not opted in. Store these against the message, and you can answer “did they get it?” for every notification.

Limits, quality and policy

  • Opt-in. You need the customer’s permission to message them, and you should record it.
  • Quality rating. WhatsApp tracks how customers react to your messages, such as blocks and reports.
  • Messaging limits. The number of customers you can start conversations with each day is capped, and the cap rises as your quality stays high.
  • Pricing. Meta bills template messages by category and destination country. Rates change from time to time.

What a production-ready integration needs

  1. Webhook with signature verification and fast acknowledgement
  2. A queue between the webhook and your business logic
  3. De-duplication on the message ID
  4. A store of conversations, messages, statuses and opt-in records
  5. Retries with back-off for sends that fail
  6. A way for people to take over from a bot
  7. Logging and alerts, so a broken integration is noticed in minutes, not days
  8. Secrets kept server-side and rotated

That list is the difference between a demo and something a business can depend on. It is also what our WhatsApp Cloud API integration service delivers.

Keep reading

WhatsApp is a trademark of Meta Platforms, Inc. Stack Bridge Labs is an independent software company and is not affiliated with, endorsed by or sponsored by WhatsApp or Meta. Conversations, names, numbers and templates shown on this page are fictional examples.