Networking ยท Business Messaging ยท Cloud API
๐Ÿ’ฌ
Architecture DeepDive
WhatsApp Business Platform

WhatsApp Business Platform Architecture: Templates, Sessions, and Webhooks

Two billion people use WhatsApp every day. The Cloud API is not a chat socket. It is a constrained messaging protocol: session states, pre-approved templates, and per-message billing. If you skip those rules, messages fail silently or the account gets flagged.

By Barnabas Waweru ยท August 17, 2026 ยท ~15 min read ยท Networking
ansi ยท wordmark ยท whatsapp business
โ–ˆโ–ˆโ•—    โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•—  โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— 
โ–ˆโ–ˆโ•‘    โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘  โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—
โ–ˆโ–ˆโ•‘ โ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•‘   โ–ˆโ–ˆโ•‘   โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•
โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•‘   โ–ˆโ–ˆโ•‘   โ•šโ•โ•โ•โ•โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ•โ• 
โ•šโ–ˆโ–ˆโ–ˆโ•”โ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘  โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘  โ–ˆโ–ˆโ•‘   โ–ˆโ–ˆโ•‘   โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘  โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘     โ–ˆโ–ˆโ•‘     
 โ•šโ•โ•โ•โ•šโ•โ•โ• โ•šโ•โ•  โ•šโ•โ•โ•šโ•โ•  โ•šโ•โ•   โ•šโ•โ•   โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•  โ•šโ•โ•โ•šโ•โ•     โ•šโ•โ•     

โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—   โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ•—   โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—
โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘   โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ•—  โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•
โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•‘   โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—  โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—
โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘   โ–ˆโ–ˆโ•‘โ•šโ•โ•โ•โ•โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•  โ•šโ•โ•โ•โ•โ–ˆโ–ˆโ•‘โ•šโ•โ•โ•โ•โ–ˆโ–ˆโ•‘
โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•‘
โ•šโ•โ•โ•โ•โ•โ•  โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•šโ•โ•  โ•šโ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•

The Reframe

WhatsApp is not an SMS replacement with a green icon. The Meta Cloud API is a regulated messaging channel with hard protocol rules: a 24-hour session window that gates every message type, a three-category template system that must pass editorial review before any message can be initiated, a quality score that gates your ability to scale, and per-message billing that changed in July 2025. Miss any of these and your messages either fail silently or your account gets flagged.

Core Abstraction

The WhatsApp Cloud API is an asymmetric duplex channel. You send outbound via REST (POST /messages). Inbound messages and delivery events arrive via HTTPS webhooks Meta pushes to you. What you can send outbound depends entirely on whether a user-initiated session is open, that asymmetry is the entire architecture constraint you're building around.

REST Send Layer
Every outbound message is a POST to graph.facebook.com/v23.0/{PHONE_NUMBER_ID}/messages with a Bearer system-user token.
24-Hour Session Window
A customer-service window opens when a user messages you. It lasts 24 hours. Inside it, any message type is allowed. Outside it, only approved templates may be sent.
Template System
Three categories (MARKETING, UTILITY, AUTHENTICATION), each reviewed by Meta before use. Only APPROVED templates can send. PENDING and REJECTED templates fail silently.
Webhook Inbound
Meta POSTs events to your HTTPS endpoint. You verify X-Hub-Signature-256, return 200 immediately, and process asynchronously. Synchronous handling causes retry floods.
WhatsApp Flows
Multi-screen native UI journeys (forms, booking, surveys) embedded directly in the chat thread via declarative Flow JSON. No external browser or webview needed.
Per-Message Pricing
July 2025: old conversation pricing is retired. Every delivered template is billed by category. Utility templates inside an open service window are free.

The Graph API Foundation

Everything is the Graph API

WhatsApp Cloud API is not a standalone product, it is a specialized surface over graph.facebook.com. The same Graph versioning rules, error model, token taxonomy, and rate limit headers apply. Understanding the Graph once means understanding every Meta product. The WhatsApp-specific pieces are the phone number node, the WABA (WhatsApp Business Account) node, and the /messages edge.

// WhatsApp Cloud API, Object Hierarchy
Meta App (App ID + App Secret)
  โ”‚
  โ”œโ”€โ”€ WhatsApp Business Account (WABA node)
  โ”‚     โ”œโ”€โ”€ Phone Number 1  (PHONE_NUMBER_ID)
  โ”‚     โ”‚     โ””โ”€โ”€ POST /messages   โ†’ outbound send
  โ”‚     โ”œโ”€โ”€ Phone Number 2
  โ”‚     โ”œโ”€โ”€ Message Templates       (per WABA, per language)
  โ”‚     โ””โ”€โ”€ Webhook Subscription    (WABA-level events)
  โ”‚
  โ”œโ”€โ”€ System User                   (production credential)
  โ”‚     โ””โ”€โ”€ System User Access Token  (long-lived, non-expiring)
  โ”‚
  โ””โ”€โ”€ App Dashboard
        โ”œโ”€โ”€ App Secret              (webhook signature key)
        โ””โ”€โ”€ App Access Token        (app-level ops)

Token Taxonomy

Token type determines what you can do and for how long. The correct production credential is a system user access token, not a user access token, not a page token. Regular user tokens expire in ~24 hours, which is a silent footgun for production servers. System user tokens are long-lived, business-scoped, and can be configured to never expire.

Token Type Lifetime Use
User access token (short) 1โ€“2 hours Client-side reads after login
User access token (long) ~60 days Server calls on behalf of a person
System user token Configurable, non-expiring โœ“ Production server automation
Business integration token Long Multi-tenant SaaS (Tech Provider, Embedded Signup)
API Versioning, Always Pin

Current stable Graph version: v23.0. Unversioned calls default to the oldest supported version, a silent footgun. Pin the version in code. Graph versions are supported for roughly two years; track the changelog to plan upgrades. All examples in this article use https://graph.facebook.com/v23.0/....

The 24-Hour Session Window

The session window is the central constraint of the entire platform. It is not a rate limit, it is a policy gate that determines which message types you are allowed to send. Every architectural decision flows from it.

// Session Window State Machine
  USER SENDS MESSAGE
         โ”‚
         โ–ผ
  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
  โ”‚   Customer-Service Window OPEN               โ”‚
  โ”‚   Duration: 24 hours from last user message  โ”‚
  โ”‚                                              โ”‚
  โ”‚   โœ“ text, image, video, audio, document      โ”‚
  โ”‚   โœ“ interactive (buttons, lists)             โ”‚
  โ”‚   โœ“ location, reaction, contacts             โ”‚
  โ”‚   โœ“ UTILITY templates (free)                 โ”‚
  โ”‚   โœ“ MARKETING templates (billed)             โ”‚
  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                       โ”‚ 24 hours pass
                       โ–ผ
  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
  โ”‚   Window CLOSED                              โ”‚
  โ”‚                                              โ”‚
  โ”‚   โœ— free-form text, silently dropped        โ”‚
  โ”‚   โœ— interactive messages, silently dropped  โ”‚
  โ”‚                                              โ”‚
  โ”‚   โœ“ APPROVED template messages ONLY          โ”‚
  โ”‚     (MARKETING, UTILITY billed, AUTH billed) โ”‚
  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

  EXCEPTION: Click-to-WhatsApp (CTWA) ads open a 72-hour window, not 24 h.

Why This Shapes Everything

The session window means WhatsApp does not behave like email or SMS. You cannot cold-message users whenever you want. You must either:

  • Wait for the user to message first, then respond within 24 hours with any message type.
  • Send an approved template to initiate or continue outside the window, billed per message.
  • Run a CTWA ad campaign, earns a 72-hour free window per click, useful for marketing flows.

The practical implication: your chatbot's free-form replies only work while a session is open. Outside the window, the bot must initiate with a template or wait. Build your state machine around this from the start.

Silent Drop, The Hidden Failure Mode

Attempting to send a free-form message outside a session window, or sending a PENDING or REJECTED template, does not return an error in the way you expect. The API returns a 200 with a wamid, but the message is never delivered. You only discover this through the delivery status webhook (status: failed) or by watching the database and noticing messages that never reached delivered. Build explicit delivery tracking from day one.

Template Architecture

Templates are the only message type that can cross session boundaries. They are pre-approved blueprints stored in your WABA, reviewed by Meta before use, and billed based on category and delivery. Getting the category right at submission time is critical, Meta re-categorizes templates and bills accordingly, regardless of what you submitted.

MARKETING
Promotions, offers, newsletters. Strictest review. Billed on every delivery, always, no exceptions.
Examples: flash sale alert, product launch, re-engagement
UTILITY
Transactional updates. Free inside an open service window; billed outside. The workhorse category for SaaS and e-commerce.
Examples: order shipped, appointment reminder, payment receipt
AUTHENTICATION
OTPs and verification codes. Dedicated OTP component with copy-code or one-tap autofill button. Volume tiers reduce unit cost. Billed per delivery.
Examples: login OTP, phone verification, MFA code

Template Lifecycle

1
Create via API or WhatsApp Manager
POST /v23.0/{WABA_ID}/message_templates with name, language, category, and components. Include realistic example values, reviewers use them. Status becomes PENDING.
2
Meta Review
Automated and human review checks category accuracy, prohibited content, and opt-in requirements. Marketing templates face stricter scrutiny. Approval time varies from minutes to days. Poll GET /{WABA_ID}/message_templates or listen for the message_template_status_update webhook event.
3
APPROVED, Ready to Send
Status is APPROVED. Templates approved per language code, en and en_US are separate approvals. Send using type: "template" in the messages payload with component parameters substituted at send time.
4
Ongoing Quality Monitoring
Delivered templates accumulate quality signals (blocks, reports). Status can move to PAUSED (rate limited) or DISABLED if quality drops. A UTILITY template submitted with marketing content gets recategorized to MARKETING and billed accordingly.

Template Payload

Parameters are substituted at send time into the approved template body. The API version is pinned in the URL. The messaging_product field is always "whatsapp".

POST https://graph.facebook.com/v23.0/{PHONE_NUMBER_ID}/messages
Authorization: Bearer {SYSTEM_USER_TOKEN}
Content-Type: application/json

{
  "messaging_product": "whatsapp",
  "to": "254712345678",           // E.164, no leading +
  "type": "template",
  "template": {
    "name": "order_update",
    "language": { "code": "en_US" },
    "components": [
      {
        "type": "body",
        "parameters": [
          { "type": "text", "text": "Amani" },
          { "type": "text", "text": "#4821" },
          { "type": "text", "text": "out for delivery" }
        ]
      }
    ]
  }
}
Phone Number Format

The to field takes E.164 format without a leading +, e.g. 254712345678 for Kenya. Twilio's WhatsApp integration additionally requires the whatsapp:+ prefix and a leading +. Daraja (M-Pesa) also uses the 254... format but normalize explicitly per API, never reuse a string built for one system in another.

Webhook Architecture

Every inbound message, every delivery event (sent, delivered, read, failed), and every template status change arrives via webhook. The webhook is your only source of truth for what actually happened. Getting the security and processing model right protects you from both injection attacks and retry cascades.

// Webhook Processing Architecture (Queue-First)
  META SERVERS
       โ”‚
       โ”‚  POST /webhook
       โ”‚  X-Hub-Signature-256: sha256=<hmac-hex>
       โ–ผ
  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
  โ”‚  1. Verify HMAC-SHA256 of RAW body bytes        โ”‚
  โ”‚     (constant-time comparison, timing attacks) โ”‚
  โ”‚                                                 โ”‚
  โ”‚  2. If invalid โ†’ 401, drop                      โ”‚
  โ”‚                                                 โ”‚
  โ”‚  3. If valid โ†’ enqueue payload โ†’ return 200     โ”‚
  โ”‚     (must return 200 before Meta's timeout)     โ”‚
  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                          โ”‚
              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
              โ–ผ                          โ–ผ
        Message Queue              Event Queue
        (inbound msgs)             (status events)
              โ”‚                          โ”‚
              โ–ผ                          โ–ผ
        Async Worker               Async Worker
        (parse, respond,           (update delivery
         session check,             state, analytics,
         route to bot)              alert on failure)

  โš  NEVER: process synchronously, parse then re-stringify for signature,
           or store raw payloads without enqueuing first.

Webhook Verification, Security Perimeter

Meta signs every POST with X-Hub-Signature-256: sha256=<hex>, HMAC-SHA256 of the raw request body bytes, keyed by your App Secret. Two critical rules: validate against the raw body (never JSON.stringify(parsedBody), whitespace differences break it), and use a constant-time comparison to prevent timing attacks.

// TypeScript, Next.js App Router route handler (simplified)
import { createHmac, timingSafeEqual } from "crypto";

export async function POST(request: Request) {
  const rawBody = await request.arrayBuffer();
  const rawBytes = Buffer.from(rawBody);

  const sig = request.headers.get("x-hub-signature-256") ?? "";
  const expected = "sha256=" + createHmac("sha256", process.env.WHATSAPP_APP_SECRET!)
    .update(rawBytes)
    .digest("hex");

  // Constant-time comparison prevents timing attacks
  const valid =
    sig.length === expected.length &&
    timingSafeEqual(Buffer.from(sig), Buffer.from(expected));

  if (!valid) return new Response("Unauthorized", { status: 401 });

  // Enqueue immediately, process asynchronously
  await queue.add("whatsapp-event", JSON.parse(rawBytes.toString("utf-8")));

  return new Response("OK", { status: 200 }); // Must return before Meta's timeout
}

Webhook Event Structure

Every webhook POST wraps events in an entry array. Inbound messages and delivery statuses can arrive in the same payload, always handle both paths.

// Inbound message event
{
  "object": "whatsapp_business_account",
  "entry": [{
    "id": "{WABA_ID}",
    "changes": [{
      "field": "messages",
      "value": {
        "metadata": { "phone_number_id": "..." },
        "messages": [{
          "id": "wamid.xxx",        // Use this for reactions/read receipts
          "from": "254712345678",
          "type": "text",
          "text": { "body": "Habari!" },
          "timestamp": "1723890000"
        }],
        "statuses": [{              // Delivery status for your outbound messages
          "id": "wamid.yyy",
          "status": "delivered",    // sent | delivered | read | failed
          "recipient_id": "254712345678",
          "timestamp": "1723890010"
        }]
      }
    }]
  }]
}
Rate Limits, Monitor X-App-Usage

Graph API responses include an X-App-Usage header, a JSON object with call_count, total_time, and total_cputime expressed as percentages. Throttle proactively before any value hits 100. The API returns error code 4 for app-level throttling and code 17 for user-level. Implement exponential backoff on these codes.

WhatsApp Flows, Native UI in Chat

WhatsApp Flows is a declarative UI framework that renders multi-screen, native UI journeys inside the chat thread. No external browser, no webview. Users fill forms, book appointments, and complete lead-capture sequences without leaving WhatsApp. From an architecture standpoint, Flows turns your webhook endpoint into a UI backend.

Two Build Modes

Mode How it works When to use
Static Flow Pure Flow JSON, no server. All screen logic is declared in the JSON. Collected data arrives at your webhook when the user submits. Lead capture, surveys, simple forms. Fast to build, no data endpoint to secure.
Dynamic Flow Your encrypted data endpoint receives data_exchange calls between screens. You validate input, fetch live data, and route the user. All traffic is end-to-end encrypted with your WABA key pair. Booking with live availability, conditional routing, real-time validation, personalized flows.
// Dynamic Flow, Encrypted Data Endpoint
  WhatsApp App (on user's phone)
       โ”‚
       โ”‚  screen transition / submit
       โ–ผ
  WhatsApp Infrastructure
       โ”‚  encrypts request with your WABA public key
       โ”‚
       โ”‚  POST /your-flow-endpoint
       โ”‚  (encrypted body)
       โ–ผ
  Your Server
       โ”‚  1. Decrypt with WABA private key
       โ”‚  2. Parse action (screen_0_field, navigation_screen, ping)
       โ”‚  3. Apply business logic (validate, fetch live data)
       โ”‚  4. Encrypt response with same key pair
       โ”‚  5. Return encrypted response
       โ–ผ
  WhatsApp Infrastructure โ†’ renders next screen on user's device
Flows vs Interactive Messages

Interactive messages (reply buttons, list menus) work inside a session window and cover simple one-step interactions, up to 3 buttons or 10 list rows. Flows handle multi-step, multi-screen journeys that go beyond what button/list interactions can express. They require more setup (Flow JSON authoring, key pair, optional data endpoint) but dramatically increase what you can accomplish inside the chat thread without redirecting to a browser.

Cost Reality Check

Pricing Model Changed July 2025

Meta retired conversation-based pricing in July 2025. Every delivered template message is now billed individually by category. There is no free monthly conversation tier anymore. If your cost model was built on the old system, recalculate now.

Per-Message Billing Model

Category Inside Window Outside Window Note
MARKETING Billed Billed Always billed on delivery
UTILITY Free Billed Best cost profile for transactional SaaS
AUTHENTICATION Billed Billed Volume tiers reduce unit cost monthly
Service (free-form) Free Not allowed Chatbot replies inside window cost nothing

Messaging Limits, The Portfolio-Wide Tier Ladder

As of October 2025, messaging limits are set per business portfolio (not per phone number) and cap unique users you can message outside a service window per rolling 24 hours.

250/day
New portfolio (unverified business), default starting tier
2,000/day
After business verification + algorithmic quality volume
10,000/day
Algorithmic scaling, quality score must stay Green
100K+/day
Further algorithmic scaling โ†’ unlimited

Scaling is algorithmic, not purchasable. You cannot buy a higher tier. Quality rating (Green / Yellow / Red) computed from blocks and reports determines whether you can scale up. A low quality score blocks upward movement even with sufficient volume. Practical levers: clean opt-in lists, message relevance, frequency discipline, easy opt-out in marketing templates.

Cost Optimization Strategy

Maximize free service messages by keeping the conversation open: respond to every user message quickly, encourage back-and-forth, and send UTILITY templates only when you genuinely need to restart a closed window. For Kenya (KE) deployments, verify the KE rate card separately, emerging market rates differ from US rates. And never misclassify marketing content as UTILITY, Meta re-categorizes and bills at the MARKETING rate.

Platform Algorithms, Quality and Rate Limits

Quality Score
Green / Yellow / Red computed from recipient blocks and reports over recent messages. Since October 2025, low quality no longer auto-downgrades limits but permanently blocks upward scaling until resolved.
App-Level Rate Limits
Graph API calls per rolling hour computed from your app's active user engagement. Higher daily usage earns a higher ceiling. Monitor X-App-Usage (JSON: call_count, total_time, total_cputime as %). Back off before any value hits 100.
Error Codes to Handle
code 4: app rate limit. code 17: user rate limit. code 190: invalid/expired token. code 131026-series: message undeliverable (check specific subcode). Implement exponential backoff on 4 and 17; alert and rotate on 190.
Delivery Tracking
Track every wamid through its lifecycle: sent โ†’ delivered โ†’ read. Failed status with a subcode tells you why. Only delivered messages bill, undelivered (e.g. invalid number) are not charged.

Key Takeaways

1
The 24-hour window is your primary architectural constraint
Design your session state machine around it from day one. Every chatbot response, every proactive outreach flow, and every integration with CRM or e-commerce systems must account for whether a user service window is open.
2
System user tokens are the production credential, no exceptions
Regular user access tokens expire in ~24 hours. A server running on a user token will silently fail overnight. Generate a system user in Meta Business Suite, assign it WABA permissions, and generate a non-expiring token before deploying.
3
Webhook architecture must be queue-first
Return 200 immediately after signature validation. Process asynchronously. Any synchronous processing that exceeds Meta's timeout triggers exponential-backoff retries that flood your endpoint. This is not optional at scale.
4
Validate webhook signatures against raw body bytes only
Never compute the HMAC against JSON.stringify(parsedBody). Whitespace in the serialized JSON may differ from what Meta signed. Use a constant-time comparison (timingSafeEqual) to prevent timing attacks.
5
Category accuracy determines your billing
Meta re-categorizes misclassified templates and bills at the correct (typically higher) rate regardless of what you submitted. UTILITY is the right category for transactional messages and is free inside an open service window, the best cost profile for SaaS and e-commerce.
6
Scaling is earned, not purchased, quality is the gate
The messaging limit tier ladder (250 โ†’ 2,000 โ†’ 10,000 โ†’ 100,000 โ†’ unlimited) advances algorithmically based on quality signals from recipient behavior. A low quality rating blocks upward scaling permanently until resolved. Build clean opt-in, message relevance, and easy opt-out from the start.
// Official References