# Bf Waba Expert

> Full Meta WhatsApp Cloud API (WABA) senior integration expert — direct Graph API v26.0 (no BSP, no MCP). Covers sending all message types (text, media, interactive buttons/lists, catalog, flows, templates, reactions, location, contacts), webhook setup with HMAC-SHA256 verification and anti-XSS challenge handling, System User Tokens, 24h service windows, per-message pricing model, Flow JSON 7.3, Coexistence, automated diagnostics with --fix, and resolving the 3 silent failure modes (WABA unsubscribed, missing webhook fields, token asset assignment, opaque error codes). Includes production Node.js/TypeScript and Python boilerplates. Triggers on any mention of WhatsApp Cloud API, WABA, Meta Graph API WhatsApp, WhatsApp webhooks, templates, messaging, or troubleshooting silent WhatsApp delivery failures.

- Skill: `bflabsai/bf-waba-expert` (Agent Skill, multi-file: 6 files)
- Install (CLI): `npx skillmds@latest add bflabsai/bf-waba-expert`
- Raw SKILL.md: https://api.skillmd.com/api/skills/bflabsai/bf-waba-expert/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- License: MIT
- Author: BFLabsAI (https://skillmd.com/u/bflabsai)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/bflabsai/bf-waba-expert

---


# BF WABA Expert (WhatsApp Cloud API)

Direct, production-grade integration and diagnostics for **Meta's WhatsApp Cloud API (Graph API v26.0)**. Zero intermediary BSPs (no Twilio, Zenvia, Wassenger) and zero MCP dependencies.

---

## When to Use

Activate this skill whenever:
- Implementing, reviewing, or fixing WhatsApp Cloud API direct integrations (`graph.facebook.com`).
- Sending messages: text, media (image, audio, video, document), interactive (buttons, list, catalog, CTA), location, contacts, reactions, or templates.
- Configuring webhooks: GET verification handshake, POST payload parsing, HMAC-SHA256 signature verification, and delivery/read/failed status processing.
- Investigating **silent delivery failures**: webhook returns 200 OK or panel shows "connected successfully" but customer messages never arrive.
- Managing WhatsApp Business Accounts (WABA): System User Tokens, phone number registration, 2-step verification, display names, and Coexistence (App + Cloud API on same number).
- Working with message templates (marketing, utility, authentication), variable mapping, and the 24-hour service window.
- Scaffolding or debugging backend implementations in Node.js (TypeScript) or Python (FastAPI/httpx).

---

## Quick Reference (Graph API v26.0)

| Parameter | Value |
|---|---|
| **Base URL** | `https://graph.facebook.com/v26.0` |
| **Send Messages** | `POST /{phone-number-id}/messages` |
| **Upload Media** | `POST /{phone-number-id}/media` |
| **Query Media URL** | `GET /{media-id}` |
| **WABA Subscribed Apps** | `POST /{waba-id}/subscribed_apps` (Critical!) |
| **Webhook Field Subs** | `POST /{app-id}/subscriptions` |
| **Auth Header** | `Authorization: Bearer {system-user-or-access-token}` |
| **Signature Header** | `X-Hub-Signature-256: sha256={hmac_hash}` |
| **Phone Format** | Strictly E.164: `+{country_code}{number}` without spaces, dashes, or leading zeros |
| **Rate Limits** | Cloud API: 80 msgs/sec default tier (scales up to 500+ msgs/sec based on quality) |
| **Pricing Model** | Per-message pricing (effective since July 2025; service window rules updated 2026) |

---

## Core Operational Law: The 3 Silent Failure Modes

In Meta's Cloud API, **the default failure mode is silence**. No error is returned, the developer dashboard shows green checks, test webhooks succeed, yet customer messages never arrive. Always check these three invisible steps:

1. **WABA Not Subscribed to the App:**
   - Meta requires explicitly binding the WABA to your App ID. Without this, webhook pings from the dashboard work, but real customer messages are dropped silently.
   - Fix: `POST https://graph.facebook.com/v26.0/{WABA_ID}/subscribed_apps`
2. **Webhook Field Subscriptions Missing:**
   - The app must subscribe specifically to the `messages` and `smb_message_echoes` fields under `whatsapp_business_account`. Updating your webhook URL in Meta Dashboard frequently unchecks these fields silently!
   - Fix: `POST https://graph.facebook.com/v26.0/{APP_ID}/subscriptions?object=whatsapp_business_account&fields=messages,smb_message_echoes` (requires App Access Token `{app_id}|{app_secret}`).
3. **Token Expiration & Missing Asset Assignment:**
   - Temporary dashboard tokens expire after 24h. Production requires a **Permanent System User Token**.
   - Simply having the permissions `whatsapp_business_messaging` and `whatsapp_business_management` is **not enough**: the WABA asset must be explicitly **assigned** to the System User in Business Manager (`business.facebook.com` → Accounts → WhatsApp Accounts → Assign People / System Users).

### Automated Healing with `diagnose.py`

Run the bundled diagnostic script to identify and automatically repair these issues:

```bash
# Inspection & report only:
python scripts/diagnose.py

# Automatically subscribe WABA and webhook fields:
python scripts/diagnose.py --fix
```

---

## Architecture & Workflows

### 1. Inbound Webhook Pipeline

A production webhook server must execute three steps in strict order:

```
Meta GET Handshake  ──► Verify hub.verify_token ──► Return hub.challenge as text/plain (200 OK)
Meta POST Event     ──► Compute HMAC-SHA256 (raw body) ──► Constant-time compare X-Hub-Signature-256
                    ──► Return 200 OK immediately (<3s) ──► Dispatch payload to async worker/queue
```

*Security Invariants:*
- **Reflected XSS Prevention:** Always respond to `hub.challenge` with `Content-Type: text/plain` and validate challenge character set (`^[A-Za-z0-9_\-]+$`).
- **Timing Attacks:** Validate signatures using constant-time comparison (`crypto.timingSafeEqual` in Node.js, `hmac.compare_digest` in Python).
- **Fast Ack (<3s):** Meta retries exponentially if your webhook takes longer than 3 seconds. Return 200 OK before heavy business logic or AI processing.
- **Idempotency:** WhatsApp webhooks may retry delivery. Deduplicate incoming events by `entry[].changes[].value.messages[].id`.

### 2. Outbound Messaging Pipeline

All messages use `POST /{phone-number-id}/messages`.

```json
{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "5511999999999",
  "type": "text",
  "text": { "body": "Olá! Como posso ajudar?", "preview_url": false }
}
```

- **Session Window (24h):** Free-form messages (text, media, interactive, audio, location) can **only** be sent within 24 hours of the user's last inbound message.
- **Outside 24h Window:** You **must** use an approved Meta Message Template (`type: "template"`). Sending free-form text outside the window returns error `131047` (`Re-engagement message`).
- **Mark as Read:** Always acknowledge customer messages to display blue double ticks:
  `POST /{phone-number-id}/messages` with `{"messaging_product": "whatsapp", "status": "read", "message_id": "<ID>"}`.

---

## Message Types Quick Guide

| Type | Payload Key | Key Constraints |
|---|---|---|
| **Text** | `"text": {"body": "..."}` | Max 4,096 chars. Markdown formatting: `*bold*`, `_italic_`, `~strike~`, ````code````. |
| **Image** | `"image": {"id": "..."}` or `{"link": "..."}` | JPG, PNG. Max 5 MB. Caption max 1,024 chars. |
| **Audio / Voice** | `"audio": {"id": "..."}` | AAC, MP4, AMR, MP3, OGG (codecs=opus for PTT). Max 16 MB. |
| **Document** | `"document": {"id": "...", "filename": "..."}` | PDF, DOCX, XLSX, etc. Max 100 MB. |
| **Interactive Buttons** | `"interactive": {"type": "button", ...}` | Max 3 quick-reply buttons. Button title max 20 chars. |
| **Interactive List** | `"interactive": {"type": "list", ...}` | Max 10 rows total across all sections. Button title max 20 chars. |
| **Reaction** | `"reaction": {"message_id": "...", "emoji": "👍"}` | Single UTF-8 emoji or `""` to remove reaction. |
| **Location** | `"location": {"latitude": -23.55, "longitude": -46.63}` | Lat/Long float, optional `name` and `address`. |
| **Template** | `"template": {"name": "...", "language": {"code": "pt_BR"}}` | Pre-approved in WhatsApp Manager. Components: `header`, `body`, `button`. |
| **Flows** | `"interactive": {"type": "nfm_reply", ...}` | Form-based native workflows (Flow JSON 7.3). |

*Full payload schemas and examples available in [references/messaging-types.md](references/messaging-types.md).*

---

## Troubleshooting & Error Taxonomy

| Error Code | Meaning | Root Cause & Resolution |
|---|---|---|
| **190** | Invalid OAuth Access Token | Token expired or revoked. Generate a permanent System User Token. |
| **100** | Invalid Parameter | Invalid phone number format (must be E.164) or malformed JSON payload. |
| **131030** | Recipient phone number not in allowed list | Test numbers in Development mode can only message numbers added to the recipient whitelist in Developer Dashboard. |
| **131047** | Re-engagement message | 24-hour customer service window is closed. Outbound message must be an approved **Template**. |
| **131051** | Unsupported message type | Payload structure doesn't match the declared `type` attribute. |
| **131052** | Media download error | Media URL unreachable, returned non-200, or took too long to respond. |
| **131053** | Media upload error | File format not supported or exceeded file size limit for the media type. |
| **130429** | Rate limit hit | Sending too fast for current messaging tier (Tier 1: 1k, Tier 2: 10k, Tier 3: 100k, Tier 4: Unlimited per 24h). Implement exponential backoff. |

*Full error catalog and field diagnoses in [references/troubleshooting-and-diagnostics.md](references/troubleshooting-and-diagnostics.md).*

---

## Bundled Tools & Scripts

The skill provides production utilities in the `scripts/` directory:

1. **`scripts/diagnose.py`**: Full diagnostic and auto-repair utility.
   - Inspects access token validity, expiration, and scopes.
   - Verifies phone number display status and verified name.
   - Queries and binds WABA app subscription (`--fix`).
   - Checks and registers webhook field subscriptions (`--fix`).
   - Simulates external Meta GET handshake test.
2. **`scripts/send_test_message.py`**: Validates outbound message delivery with E.164 sanitization.
3. **`scripts/validate_config.py`**: Audits local `.env` configuration.
4. **`scripts/setup_project.py`**: Scaffolds a full Node.js or Python WhatsApp Cloud API microservice with secure webhooks and typed clients.

---

## Project Boilerplates

Pre-configured boilerplates ready to drop into projects:
- **Node.js (TypeScript):** `assets/boilerplate/nodejs/`
  - Express server with raw-body HMAC validation middleware.
  - Complete TypeScript types for all incoming/outgoing payloads.
  - Typed `WhatsAppClient` with automatic retries and exponential backoff.
- **Python (FastAPI):** `assets/boilerplate/python/`
  - FastAPI server with async `httpx` client.
  - HMAC-SHA256 request validator decorator.
  - Template manager and media upload/download utilities.

---

## Detailed References

For deep-dive documentation, consult the files in `references/`:
- [references/api-reference-v26.md](references/api-reference-v26.md) — Endpoints, auth tokens, headers, rate limits, and pricing.
- [references/messaging-types.md](references/messaging-types.md) — Exact JSON payload specifications for every message type.
- [references/webhooks-and-security.md](references/webhooks-and-security.md) — HMAC validation, signature headers, payload models, and deduplication.
- [references/templates-and-lifecycle.md](references/templates-and-lifecycle.md) — Template creation, approval guidelines, and parameter mapping.
- [references/troubleshooting-and-diagnostics.md](references/troubleshooting-and-diagnostics.md) — Silent failures, error codes, and Coexistence runbook.
- [references/coexistence-and-compliance.md](references/coexistence-and-compliance.md) — Coexistence setup, opt-in rules, and quality rating management.

