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?".