From 671c30eb48527a41d7fcf0288aa274708df5e181 Mon Sep 17 00:00:00 2001 From: "posthog[bot]" <206114724+posthog[bot]@users.noreply.github.com> Date: Fri, 3 Jul 2026 21:09:31 +0000 Subject: [PATCH] docs: consolidate WhatsApp template rejection troubleshooting Users hit Bad Request errors when creating WhatsApp templates and had to piece together the cause from scattered rules across templates-reference.md and the WhatsApp SKILL files. Add a single "Troubleshooting: why did my template get rejected?" section to templates-reference.md that maps each Meta failure to a plain-English cause and fix: example/variable mismatches and positional gaps that produce a Bad Request, category restrictions (MARKETING vs UTILITY vs AUTHENTICATION), and the Meta business verification requirement tied to OAuthException 139000. Surface it from observe-whatsapp's triage reference and cross-link from both skills so a human or the support chatbot can self-serve. Generated-By: PostHog Code Task-Id: 85975335-f067-4dd5-ac5a-470f31a82d6b --- .../kapso/skills/integrate-whatsapp/SKILL.md | 8 ++- .../references/templates-reference.md | 53 +++++++++++++++++++ .../kapso/skills/observe-whatsapp/SKILL.md | 4 ++ .../references/triage-reference.md | 20 +++++++ 4 files changed, 84 insertions(+), 1 deletion(-) diff --git a/plugins/kapso/skills/integrate-whatsapp/SKILL.md b/plugins/kapso/skills/integrate-whatsapp/SKILL.md index d38dd09..691619a 100644 --- a/plugins/kapso/skills/integrate-whatsapp/SKILL.md +++ b/plugins/kapso/skills/integrate-whatsapp/SKILL.md @@ -228,6 +228,12 @@ Send-time: - URL buttons need a `button` component with `sub_type: "url"` and `index` - Media headers use either `id` or `link` (never both) +Rejected at creation? Kapso forwards to Meta directly, so failures come back as Meta API +errors (often a bare Bad Request / `(#100)`). See the "Troubleshooting: why did my template +get rejected?" section in `references/templates-reference.md` for the cause → fix mapping +(example/variable mismatches, category restrictions, and OAuthException 139000 business +verification). + ## WhatsApp Flows Use Flows to build native WhatsApp forms. Read `references/whatsapp-flows-spec.md` before editing Flow JSON. @@ -377,7 +383,7 @@ node scripts/openapi-explore.mjs --spec platform search "setup link" - [references/webhooks-overview.md](references/webhooks-overview.md) - Webhook types, signature verification, retries - [references/webhooks-event-types.md](references/webhooks-event-types.md) - Available events - [references/webhooks-reference.md](references/webhooks-reference.md) - Webhook API and payload notes -- [references/templates-reference.md](references/templates-reference.md) - Template creation rules, components cheat sheet, send-time components +- [references/templates-reference.md](references/templates-reference.md) - Template creation rules, components cheat sheet, send-time components, rejection troubleshooting - [references/whatsapp-api-reference.md](references/whatsapp-api-reference.md) - Meta proxy payloads for messages and conversations - [references/whatsapp-cloud-api-js.md](references/whatsapp-cloud-api-js.md) - SDK usage for sending and reading messages - [references/whatsapp-flows-spec.md](references/whatsapp-flows-spec.md) - Flow JSON spec diff --git a/plugins/kapso/skills/integrate-whatsapp/references/templates-reference.md b/plugins/kapso/skills/integrate-whatsapp/references/templates-reference.md index eccfedd..abbf44b 100644 --- a/plugins/kapso/skills/integrate-whatsapp/references/templates-reference.md +++ b/plugins/kapso/skills/integrate-whatsapp/references/templates-reference.md @@ -75,6 +75,59 @@ If any variables appear in HEADER or BODY, you must include examples: - POSITIONAL: `example.header_text` and 2D `example.body_text`. - NAMED: `example.header_text_named_params` and `example.body_text_named_params`. +## Troubleshooting: why did my template get rejected? + +Kapso forwards create/update calls straight to Meta, so a bad template comes back as a +Meta API error (often a bare **Bad Request** / `(#100)`) rather than a Kapso validation +message. Map the failure to a cause and fix before resubmitting. + +### Bad Request (`(#100)`) at creation time — almost always example/variable mismatch + +The most common wall: the template has variables but the `example` block doesn't line up +with them. Check, in order: + +| Cause | How to spot it | Fix | +|-------|----------------|-----| +| Missing example for a HEADER/BODY variable | A `{{...}}` placeholder has no matching entry in `example` | Provide exactly one example per variable in every component that uses variables. See [Components cheat sheet](#components-cheat-sheet-creation-time). | +| Example keys don't match `parameter_format` | Using `example.body_text` (positional keys) while `parameter_format: NAMED`, or `example.body_text_named_params` while `POSITIONAL` | NAMED → `header_text_named_params` / `body_text_named_params`; POSITIONAL → `header_text` / 2D `body_text`. | +| NAMED example `param_name` doesn't match the placeholder | `{{order_id}}` in text but the example lists `param_name: "orderId"` (or a typo) | Make every `param_name` exactly equal the `{{...}}` name (lowercase + underscores). | +| Positional placeholders have gaps | Text uses `{{1}}` and `{{3}}` but not `{{2}}`, or examples don't cover every index | Positional variables must be sequential with no gaps, and `body_text` must supply one value per placeholder. | +| Example count doesn't match variable count | 2 variables but 1 example (or vice-versa) | The number of examples must equal the number of variables in that component. | + +Positional body examples are a **2D array** (`[["ORDER-123", "Alex"]]`), not a flat one — +a flat array is a frequent Bad Request cause. + +### Rejected for the wrong category + +Categories aren't interchangeable; Meta rejects (or silently re-categorizes) templates +whose content doesn't fit: + +| Category | Allowed content | Common rejection | +|----------|-----------------|-------------------| +| MARKETING | Promotions, offers, announcements | — | +| UTILITY | Transactional updates tied to an existing order/account | Promotional wording in a UTILITY template → rejected or bumped to MARKETING | +| AUTHENTICATION | OTP / verification only | Custom body text (body is **fixed by Meta**), or no OTP button; also **requires Meta business verification** (see below) | + +If you need custom OTP wording, use **UTILITY** instead of AUTHENTICATION. + +### OAuthException 139000 — WABA not verified + +A `139000` (Integrity) error means the WhatsApp Business Account has not completed **Meta +business verification**. This blocks AUTHENTICATION templates and can block sending. Fix: +verify the business in Meta Security Center / Business Manager, then retry. This is the same +error surfaced when Flows integrity checks fail. + +### Duplicate name / language + +Creating a template whose `name` + `language` already exists returns an error. List existing +templates first (`node scripts/list-templates.mjs`) and pick a new name or update the +existing one via `hsm_id`. + +### Button rejections + +See [Button ordering rules](#buttons): don't interleave QUICK_REPLY with URL/PHONE_NUMBER, +and dynamic URL variables must sit at the end of the URL. + ## Components cheat sheet (creation time) ### Header (TEXT, named) diff --git a/plugins/kapso/skills/observe-whatsapp/SKILL.md b/plugins/kapso/skills/observe-whatsapp/SKILL.md index 0becde0..dec3b77 100644 --- a/plugins/kapso/skills/observe-whatsapp/SKILL.md +++ b/plugins/kapso/skills/observe-whatsapp/SKILL.md @@ -42,6 +42,10 @@ Preferred path: 2. Run number health: `kapso whatsapp numbers health --phone-number "" --output human` 3. Inspect related templates when relevant: `kapso whatsapp templates list --phone-number "" --output json` +For **template creation failures** (Bad Request on `whatsapp_templates/new`, rejected or +recategorized templates, OAuthException 139000), see the "Template creation rejected" section +in `references/triage-reference.md`, which maps each Meta failure to a cause and fix. + Fallback path: 1. Message errors: `node scripts/errors.js` 2. API logs: `node scripts/api-logs.js` diff --git a/plugins/kapso/skills/observe-whatsapp/references/triage-reference.md b/plugins/kapso/skills/observe-whatsapp/references/triage-reference.md index 96f96fe..7f9534c 100644 --- a/plugins/kapso/skills/observe-whatsapp/references/triage-reference.md +++ b/plugins/kapso/skills/observe-whatsapp/references/triage-reference.md @@ -23,3 +23,23 @@ 1. Review external API call logs. 2. Filter by status code or endpoint. 3. Identify auth errors, rate limits, or upstream failures. + +## Template creation rejected (Bad Request / Meta API error) + +Kapso forwards template create/update calls straight to Meta, so rejections come back as +Meta API errors (often a bare **Bad Request** / `(#100)`), not Kapso validation messages. +Don't guess — map the failure to a cause: + +1. **Bad Request at creation** — almost always an example/variable mismatch: a variable + with no example, example keys that don't match `parameter_format` (NAMED vs POSITIONAL), + a `param_name` that doesn't match the `{{...}}`, positional gaps, or a flat instead of 2D + `body_text` array. +2. **Wrong category** — promotional wording in a UTILITY template, or custom body text in an + AUTHENTICATION template (its body is fixed by Meta and it needs an OTP button). +3. **OAuthException 139000** — the WABA is not verified in Meta business verification; this + blocks AUTHENTICATION templates and can block sending. +4. **Duplicate name/language** — a template with that `name` + `language` already exists. + +Full cause → fix mapping (with corrected example payloads) lives in the +`integrate-whatsapp` skill: `references/templates-reference.md` → "Troubleshooting: why did +my template get rejected?".