Skip to content

WhatsApp Pre-Submission Inspect

WhatsApp Inspect is a pre-submission format checker. It catches the issues that cause Meta (WhatsApp Business Platform) to reject a template — placeholder rules, component limits, category — before you submit the template for approval, so you avoid a rejection round-trip.

Warning

Inspect is not WABA approval, and Synapse does not submit templates to Meta for you. You create the template in your Meta / provider console and submit it there; Synapse references the approved template by its provider SID. WhatsApp Inspect runs inside Synapse against your stored template and tells you whether it is likely to pass Meta's format rules. A clean Inspect result does not guarantee Meta approval, and it does not send anything.


What it checks

WhatsApp Inspect runs a single stage of pre-submission analysis against your stored WhatsApp template (body_nlt, variable_schema, category, language). It falls into three groups:

  1. Meta placeholder rules — the {{1}}, {{2}} positional-variable constraints Meta enforces at submission time. Getting these wrong is the most common cause of a hard rejection.
  2. Component limits — Meta's character limits on the body (and, in future, header / footer / button components).
  3. NLT rendering — the same plain-English expression checks the other channels use, against a sample contact.

Severity discipline

WhatsApp Inspect is advisory: it does not gate a Synapse send (the send gate is Meta approval plus the 24-hour customer-service window). Because of that, almost everything is a warning. The only critical is a required NLT miss, which is a real whole-message drop at send time.


Variable / placeholder rules

Meta requires positional variables in a template body to follow strict rules. Violating any of them is a hard rejection on submission.

FindingSeverityFires when
WA_VARIABLE_COUNT_MISMATCHwarningThe number of distinct {{n}} placeholders in the body does not equal the number of variables declared in variable_schema.
WA_PLACEHOLDER_NOT_SEQUENTIALwarningPlaceholders are not a gapless sequence starting at 1 (e.g. {{1}} and {{3}} with {{2}} missing, or a body starting at {{2}}).
WA_PLACEHOLDER_ADJACENT_OR_EDGEwarningTwo placeholders are separated only by whitespace, or a placeholder sits at the very start or end of the body.

WA_VARIABLE_COUNT_MISMATCH

Meta requires every positional variable used in the body to be declared, and the two counts to agree. The Synapse send-time binder does not cross-check this, so this is a genuinely new pre-submission check.

Fix: Reconcile the body placeholders with variable_schema — every {{n}} in the body must have a corresponding declared variable, and vice versa.

The finding context reports both sides so you can see the mismatch:

json
{
"placeholder_count": 2,
"placeholder_indices": [1, 2],
"schema_key_count": 3,
"schema_keys": ["first_name", "order_id", "eta"]
}

WA_PLACEHOLDER_NOT_SEQUENTIAL

Meta requires positional variables to be "numbered sequentially without skipping integers." A body using {{1}} and {{3}} (no {{2}}), or one starting at {{2}}, will be rejected.

Fix: Renumber the placeholders so they form a gapless sequence starting at 1 — {{1}}, {{2}}, {{3}}, …

json
{
"found": [1, 3],
"expected": [1, 2]
}

WA_PLACEHOLDER_ADJACENT_OR_EDGE

Meta rejects templates where variables are adjacent (only whitespace between two {{n}} tokens) or appear at the very start or end of the body string.

Fix: Add literal text between adjacent placeholders and ensure the body does not begin or end with a {{n}} token. For example:

Hi {{1}}, your code is {{2}}. Thanks.

json
{
"reasons": ["leading", "adjacent"]
}

Body limit

WA_BODY_OVER_LIMIT

Severity: warning — fires when body_nlt is longer than 1024 characters, Meta's maximum for a WhatsApp template body. Meta rejects the template on submission.

Note

The measured length is the raw pre-submission source, where {{n}} tokens count as their short literal form. Meta's limit applies to the rendered message, so test with realistic variable values too.

Fix: Shorten the body to 1024 characters or fewer.

json
{
"length": 1103,
"limit": 1024,
"over_by": 79
}

Category

WA_CATEGORY_INVALID

Severity: warning — fires when the template category is not one of Meta's allowed values: marketing, utility, or authentication.

This normally cannot happen through the API — the create / update schema already blocks an unknown category. It is defense-in-depth for a value written by a migration, seed, or direct database path.

Fix: Set the category to marketing, utility, or authentication.

json
{
"category": "promo",
"allowed": ["marketing", "utility", "authentication"]
}

NLT rendering

These use the same plain-English rendering checks as the other channels, run against a sample contact. They each have a dedicated finding page:

FindingSeverityPage
WA_NLT_REQUIRED_MISScriticalWA_NLT_REQUIRED_MISS
WA_NLT_UNRESOLVEDwarningWA_NLT_UNRESOLVED

Component limits (reserved)

The finding catalog defines three more component-limit checks. They do not fire today because the WhatsApp template model currently stores the message body only — it has no header, footer, or button components. These codes are reserved for when component storage is added, and are listed here for completeness:

FindingMeta limitStatus
WA_HEADER_OVER_LIMIT60 characters (text header)Reserved — no header component is stored today, so this cannot fire.
WA_FOOTER_OVER_LIMIT60 characters (footer)Reserved — no footer component is stored today, so this cannot fire.
WA_BUTTON_LABEL_OVER_LIMIT25 characters (button label)Reserved — no button component is stored today, so this cannot fire.
Note

These three checks are defensive placeholders in the catalog. They are documented here so the catalog is complete, but on today's templates they never produce a finding.


Running a WhatsApp Inspect

Trigger a run against a WhatsApp template by ID or slug:

bash
curl -X POST https://synapse-api.pyrx.tech/v1/inspect \
-H "X-WORKSPACE-ID: <workspace-uuid>" \
-H "X-API-KEY: psk_live_<hex32>" \
-H "Content-Type: application/json" \
-d '{
"channel": "whatsapp",
"whatsapp_template_slug": "order-shipped"
}'

The template is inspected regardless of its approval status — a pending or even rejected template is fully inspectable, since the whole point is catching format issues before (or after) a Meta rejection. See the Inspect API reference for the full request and response shape.