Skip to main content

Template lifecycle and approval semantics

A template is a reusable message body you author once and send many times. The endpoint contract — every field, every status value — lives in the Templates API reference. This page explains the model behind it: why templates exist as a separate object at all, how a template moves through approval, and where templates sit relative to ad-hoc bodies, flows, and campaigns.

Why templates exist

Two forces keep templates separate from a message’s body field. The first is carrier policy. On several channels a business cannot send a message body the carrier has never reviewed: WhatsApp goes through Meta’s review queue, RCS goes through MNO/MAAP review, and KakaoTalk AlimTalk / Zalo ZNS are legally template-only — the reseller must pre-approve a template before any send can reference it. On those channels the platform cannot treat the body as sender-authored text; it has to persist the authored content, submit it for review, and track the outcome as first-class state. The second is operational. Templates carry their own write-path rules. Only one route mutates templates — the canonical POST / PATCH / DELETE surface under /api/v1/messages/templates — because that is where the carrier-approval gate lives: the service decides whether a create is sent to the carrier’s review queue or activated immediately, and whether an edit has to re-submit. The top-level GET /api/v1/templates is a read-only search alias the dashboard’s command palette uses; it deliberately exposes no mutation, so no path can edit a template while bypassing the approval gate. A freeform body on a single send has no review step at all — that is what makes templates a distinct object rather than a convenience.

The lifecycle

A template carries one status value at a time: Which states are sendable depends on the channel. On an approval-required channel, only approved works — sending a draft or pending template fails, because the carrier has not signed off. On platform-only channels (SMS, MMS, email, Viber, Telegram, LINE, Messenger, Instagram, push, fax, Apple Messages), active templates send immediately and there is no review round-trip. The typical walk on an approval-required channel is draft → pending → approved, with rejected as a loop back into draft after an edit. The terminal state on any channel is archived, not deprecated: when you retire a template you archive it, and every campaign that referenced it keeps its historical association. Filter the list by where a template is in this walk with ?status= on GET /api/v1/messages/templates — e.g. ?status=pending for everything currently waiting on a carrier decision.

Channels and purposes

Two filters cut the list by what the template is for. ?channel= matches against the template’s audience channel. The value set is shared across create and list: sms, mms, whatsapp, email, viber, rcs, telegram, line, messenger, instagram, push, fax, kakao, zalo, apple_messages. Of those, four require carrier approval — whatsapp, rcs, kakao, and zalo — which is why they start at draft; the rest start at active. ?purpose= tags a template with a declared use when channel alone is too coarse. The set is closed and deliberately small today — call_permission_request is the only value, marking a WhatsApp re-engagement template for contacts whose calling permission has expired or been revoked. Templates without a tag remain general-purpose; both the create schema and the list filter accept only the closed set.

Cross-campaign analytics

A template reused across many campaigns accumulates engagement history scattered across per-campaign counters. GET /api/v1/templates/{id}/analytics consolidates it: sent, delivered, failed, opened, and clicked totals aggregated across every campaign that references the template, the derived delivery/open/click rates, and a per-campaign breakdown alongside the rollup. The template analytics guide walks the response fields and reading patterns.

Templates, bodies, flows, campaigns

The layers below exist at different altitudes; confusing them is the most common modeling mistake.
  • A body is one send’s content — the body string you pass on a single message (POST /api/v1/messages). It is ephemeral: sent once, reviewed never, reused never.
  • A template is a named, reusable message body. It survives sends, goes through carrier review once, and is referenced by name from then on.
  • A flow is a conversational or automation graph — a sequence of sends and waits, e.g. a three-step drip. Sends inside a flow still reference templates or bodies per step; the flow orchestrates, it does not author content.
  • A campaign is the targeting-and-scheduling wrapper: which contacts, when, through which flow or single send. A campaign references a template by id; the template never knows the campaign exists.
Rule of thumb: if the content is reviewed, it is a template. If it is ad-hoc and one-shot, it is a body. If it spans multiple sends with logic between them, it is a flow. If it is aimed at an audience with timing, it is a campaign.

Read and write scopes

Template management has its own API-key scope pair, separate from messages:*:
  • templates:read — list templates, fetch one, read summary counts, and pull cross-campaign analytics.
  • templates:write — create, update, or delete a template; a write-scoped key also reads.
This separation exists because authoring a template is not just sending: it is a content-authoring plus carrier-approval action, and a rejected or out-of-date template blocks every send that references it. Split keys let you mint a narrow read-only key for anything that only lists or analyzes templates, while holding writes to keys that are deliberately authorized to change what carriers see for review.

See also