Skip to main content

What it does

Creates a new WhatsApp message template and submits it to Meta for approval. A newly created template’s status is usually PENDING.

Endpoint

There are no query parameters.

Headers

string
required
Secret key in Bearer sk_... format. See Secret Key authentication.
string
required
Always application/json.

Path parameters

string
required
Application ID. Must belong to the organization (otherwise 404).

Request Body

Top-level fields

string
required
Template name (max 512 chars). Pattern: ^[a-z][a-z0-9_]*$ (must start with a lowercase letter; lowercase letters, digits, and underscores only). Must be unique.
string
required
Language code, e.g. tr, en, en_US. This is a closed list, not free-form BCP-47 — see Template Language. An unsupported code returns 422.
string
required
One of UTILITY, MARKETING, or AUTHENTICATION. Determines the component rules — see the Category rules section below, and Template Category for what each one is for.
object | null
Header component. See the header object below.
object
required
Body component. See the body object below.
Footer component. See the footer object below.
array | null
List of buttons (max 10). See the buttons object below. Not allowed together with carousel — carousel buttons belong to each card.
Turns the template into a carousel: a body bubble followed by 2–10 swipeable cards, each with its own media header, body, and buttons. MARKETING only. See the carousel card object and Carousel rules sections below.
boolean | null
If true, Meta may automatically re-classify the template’s category.
integer | null
Message time-to-live. UTILITY: 30–43200, MARKETING: 43200–2592000, AUTHENTICATION: 30–900 (or -1).
object | null
Turns the template into a limited-time offer — a MARKETING-only banner that WhatsApp renders above the body, optionally with a live expiration countdown. See the limitedTimeOffer object and Limited-time offer rules sections below.

header object

string
One of NONE (default), TEXT, IMAGE, VIDEO, DOCUMENT, LOCATION. See Header Format.
string
Only for TEXT headers (max 60 chars). Cannot start or end with a variable.
string | string[]
Variable example for a TEXT header; for media headers, the uploaded media handle.

body object

string
Body text (max 1024 chars); supports {{1}}, {{2}} variables. Cannot start or end with a variable. Required for UTILITY/MARKETING.
string[]
Example values for the variables (order matters). The count must equal the number of variables.
boolean
AUTHENTICATION only; adds the security recommendation text.
string
Footer text (max 60 chars). Cannot be used in AUTHENTICATION.
integer
AUTHENTICATION only (1–90); the code validity duration.

buttons object

Each item in the buttons array:
string
One of QUICK_REPLY, URL, PHONE_NUMBER, COPY_CODE, OTP. See Button Type.
string
Button text (2–25 chars). Required for URL / PHONE_NUMBER / QUICK_REPLY.
string
URL type target link (https://...); can be dynamic using {{1}}.
string
PHONE_NUMBER type phone in E.164 format.
string[]
Dynamic URL example, or the COPY_CODE coupon code (required for COPY_CODE).
string
For OTP: one of COPY_CODE, ONE_TAP, ZERO_TAP. See OTP Type.
string
ONE_TAP / ZERO_TAP autofill text (max 25 chars).
string
ONE_TAP / ZERO_TAP Android package name.
string
ONE_TAP / ZERO_TAP signature hash.
boolean
ZERO_TAP terms acceptance.
Each item in the carousel array is one card. Every card must be structurally identical to the others (same header format, same button types in the same order).
object
required
The card’s media header. format must be IMAGE or VIDEO — no TEXT, DOCUMENT, or LOCATION — and examples must carry the media handle from Upload Media.
object
required
The card’s body. text is required and limited to 160 chars (shorter than the 1024 of the template body). Variables and examples follow the same rules as the template body.
array
required
1–2 buttons for this card. Only QUICK_REPLY, URL, and PHONE_NUMBER are allowed — no COPY_CODE or OTP.

limitedTimeOffer object

string
required
The offer text shown on the banner (1–16 chars), e.g. "Expiring offer!".
boolean
Defaults to false. When true, WhatsApp renders an expiration countdown on the offer; the expiration timestamp itself is supplied per message when the template is sent, not here.

Category rules

AUTHENTICATION — no header; no body.text (only addSecurityRecommendation); no footer.text (only codeExpirationMinutes); buttons may only be OTP.
UTILITY / MARKETINGbody.text is required; addSecurityRecommendation and codeExpirationMinutes cannot be used; OTP buttons are not allowed; COPY_CODE is allowed in MARKETING only.
The body/header cannot start or end with a variable, and the number of examples must equal the number of variables.

Sending carousel puts the template into carousel mode: the top-level template keeps only its body bubble, and every other component moves into the cards. All of the rules below are enforced locally and fail with 422 before the request reaches Meta.
Carousel is create-only. Update Template does not accept a carousel field, so an existing carousel template cannot have its cards edited through this API — create a new template instead.
carousel and limitedTimeOffer cannot be combined in the same template (WA_TPL_052). Each card needs its own uploaded media handle, so a 5-card carousel means 5 separate Upload Media calls.

Limited-time offer rules

Sending limitedTimeOffer puts the template into limited-time offer mode, which narrows what the other components may contain. All of the rules below are enforced locally and fail with 422 before the request reaches Meta; omitting limitedTimeOffer leaves every other rule on this page unchanged.
The common pairing is one COPY_CODE button carrying the coupon code plus one URL button linking to the campaign — that is the maximum a limited-time offer template allows.
hasExpiration only controls whether the countdown is rendered. The offer’s expiration timestamp is not part of the template; it is provided per message at send time, so the same approved template can be reused for different deadlines.

Response

The envelope is { "data": {...}, "isSuccess": true } (HTTP 200). The data is a lean creation response:
boolean
true when the template was created and submitted.
object
The create response does not return components, qualityScore, rejectedReason, parameterFormat, or the DB id — use Get Template Detail or Get Templates for those.

Examples

Note that no footer is sent and there are exactly two buttons — both are requirements for a limited-time offer. The image header handle comes from Upload Media.

Errors

object
Error details with code, group, and description; isSuccess is false.

Auth / tenant

Request validation (before reaching Meta)

Every rule below is checked locally and returns 422 with group VALIDATION; the request never reaches Meta. Button rules Header rules Body rules Category rules Name rule Field-level constraints (about-style max lengths, limit ranges, unknown enum values, a missing required field) are reported by FastAPI as VAL_* validation errors instead. Returned only when carousel is present. Each row maps to a rule in the Carousel rules section above.

Limited-time offer validation (before reaching Meta)

Returned only when limitedTimeOffer is present. Each row maps to a rule in the Limited-time offer rules section above.

Meta-side