Skip to main content

Create Template

Create a new WhatsApp message template on Meta and store it locally. Templates are submitted to Meta for review and typically reach APPROVED status within minutes to 24 hours.

POST /api/v1/templates/create

For media-card carousel templates (multiple cards, each with an image/video), use Create Carousel Template instead.

Request body

FieldTypeRequiredDescription
namestringYesTemplate name — lowercase letters, numbers, underscores only (e.g., order_update). Max 512 chars.
categorystringYesMARKETING, UTILITY, or AUTHENTICATION
languagestringNoBCP-47 language code. Defaults to en_US.
waba_phone_idstringNoWhatsApp Business Account phone ID to create the template under. If omitted, Waplify uses the first WhatsApp number linked to your account.
headerobjectNoHeader component — see below
media_urlstringConditionalPublic URL for header media. Required when header.format is IMAGE, VIDEO, or DOCUMENT. We download it and upload to Meta on your behalf.
bodyobjectConditionalBody component — required for MARKETING and UTILITY
footerobjectNoFooter component (max 60 chars, no variables)
buttonsarrayNoUp to 10 interactive buttons — see below
limited_time_offerobjectNoLTO component (MARKETING only) — see below
offer_codestringNoOffer/coupon code (max 15 chars). Required if limited_time_offer is set.
add_security_recommendationbooleanNoInclude security text in auth template body
code_expiration_minutesnumberNoCode expiry (1–90 minutes) for AUTHENTICATION templates
message_send_ttl_secondsnumberNoTTL for messages sent using this template

header object

FieldTypeDescription
formatstringTEXT, IMAGE, VIDEO, DOCUMENT, or LOCATION
textstringHeader text (required when format is TEXT, max 60 chars). Supports {{1}} or {{Name}} variables.
text_exampleobjectExample values for header variables, e.g. {"1": "John"}

body object

FieldTypeDescription
textstringBody text (max 1024 chars). Supports {{1}}/{{Name}} variables.
examplesobjectExample values for each variable, e.g. {"1": "John", "2": "Order123"}
FieldTypeDescription
textstringFooter text (max 60 chars, no variables)

buttons array items

FieldTypeDescription
typestringQUICK_REPLY, URL, PHONE_NUMBER, COPY_CODE, or FLOW
textstringButton label (max 25 chars)
urlstringURL for URL buttons. Supports {{1}} suffix. WhatsApp domains are not allowed.
url_examplestringExample value used when url contains {{1}}
phone_numberstringPhone number for PHONE_NUMBER buttons
copy_code_examplestringExample coupon code for COPY_CODE buttons
flow_idstringFlow ID for FLOW buttons
flow_actionstringFlow action (default navigate)
navigate_screenstringTarget screen for FLOW buttons

Button limits: max 10 QUICK_REPLY, 2 URL, 1 PHONE_NUMBER, 1 COPY_CODE.

limited_time_offer object

FieldTypeDescription
textstringOffer heading (max 16 chars)
has_expirationbooleanShow the countdown timer (default true)

LTO templates must be MARKETING, have no footer, body ≤ 600 chars, offer_code set, and a COPY_CODE button at index 0.

Variable style

You cannot mix numbered ({{1}}) and named ({{name}}) variables in the same template — pick one style and use it consistently across header and body.

Examples

Text-only template

curl -X POST https://server.waplify.io/api/v1/templates/create \
-H "Authorization: Bearer wapl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "order_update",
"category": "UTILITY",
"language": "en_US",
"waba_phone_id": "123456789012345",
"header": {
"format": "TEXT",
"text": "Order Update"
},
"body": {
"text": "Hello {{1}}, your order {{2}} has been shipped!",
"examples": { "1": "John", "2": "ORD-12345" }
},
"footer": { "text": "Thank you for shopping with us" },
"buttons": [
{
"type": "URL",
"text": "Track Order",
"url": "https://example.com/track/{{1}}",
"url_example": "ORD-12345"
}
]
}'

Template with image header

The media_url must point to a publicly accessible JPEG or PNG (max 5 MB). Waplify downloads it and uploads the sample to Meta.

curl -X POST https://server.waplify.io/api/v1/templates/create \
-H "Authorization: Bearer wapl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "promo_banner",
"category": "MARKETING",
"language": "en_US",
"waba_phone_id": "123456789012345",
"header": { "format": "IMAGE" },
"media_url": "https://example.com/banner.jpg",
"body": {
"text": "Hi {{1}}, enjoy {{2}} off this weekend!",
"examples": { "1": "Priya", "2": "30%" }
},
"buttons": [
{ "type": "QUICK_REPLY", "text": "Shop now" },
{ "type": "QUICK_REPLY", "text": "No thanks" }
]
}'

Named variables

curl -X POST https://server.waplify.io/api/v1/templates/create \
-H "Authorization: Bearer wapl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "appointment_reminder",
"category": "UTILITY",
"language": "en_US",
"waba_phone_id": "123456789012345",
"body": {
"text": "Hi {{name}}, reminder: your appointment with {{doctor}} is on {{date}}.",
"examples": { "name": "John", "doctor": "Dr. Patel", "date": "June 15 at 10 AM" }
}
}'

Limited-time offer

curl -X POST https://server.waplify.io/api/v1/templates/create \
-H "Authorization: Bearer wapl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "flash_sale",
"category": "MARKETING",
"language": "en_US",
"waba_phone_id": "123456789012345",
"body": {
"text": "Hi {{1}}, use your exclusive code before it expires!",
"examples": { "1": "Priya" }
},
"limited_time_offer": { "text": "Limited offer", "has_expiration": true },
"offer_code": "FLASH40",
"buttons": [
{ "type": "COPY_CODE", "text": "Copy code", "copy_code_example": "FLASH40" }
]
}'

Success response (201 Created)

{
"status": "success",
"message": "Template 'order_update' created and submitted for review",
"template_id": "507f1f77bcf86cd799439012",
"meta_template_id": "1234567890123456",
"meta_status": "PENDING"
}
FieldDescription
template_idWaplify's internal template ID
meta_template_idMeta's template ID
meta_statusInitial status — usually PENDING. Poll List Templates (or run Sync Templates) to see when it becomes APPROVED.

Error responses

Invalid template name

// 422 Unprocessable Entity
{
"detail": "Template name must contain only lowercase letters, numbers, and underscores"
}

Mixed variable styles

// 422 Unprocessable Entity
{
"detail": "Cannot mix numbered ({{1}}) and named ({{name}}) variables. Use one style only."
}

Media download failed

// 400 Bad Request
{
"error": "bad_request",
"message": "Failed to download media from URL: HTTP 404"
}

Duplicate name

// 400 Bad Request
{
"error": "bad_request",
"message": "A template with this name already exists for this phone number"
}

Media file limits (for headers)

Header formatMax SizeAccepted Formats
IMAGE5 MBJPEG, PNG
VIDEO16 MBMP4
DOCUMENT100 MBPDF
After creating a template

A newly created template starts in PENDING status. Call Sync Templates or List Templates periodically to pick up the final APPROVED / REJECTED decision from Meta.