Templates
Overview
Section titled “Overview”WhatsApp Message Templates are pre-approved message formats required for sending business-initiated messages. Templates must be approved by Meta before use.
List Templates
Section titled “List Templates”Retrieve all templates for your account.
GET /api/templatesQuery Parameters
Section titled “Query Parameters”| Parameter | Type | Description |
|---|---|---|
page | integer | Page number (default: 1) |
limit | integer | Page size, 1–100. Default 50. |
status | string | Filter by status (APPROVED, PENDING, REJECTED) |
category | string | Filter by category (MARKETING, UTILITY, AUTHENTICATION) |
account | string | Filter by WhatsApp account name |
search | string | Case-insensitive match on name or display_name |
Ordered by created_at DESC.
Response
Section titled “Response”{ "status": "success", "data": { "templates": [ { "id": "uuid", "whatsapp_account": "Main Business", "meta_template_id": "123456789", "name": "order_confirmation", "display_name": "Order Confirmation", "language": "en", "category": "UTILITY", "status": "APPROVED", "header_type": "IMAGE", "header_content": "", "body_content": "Hi {{1}}, your order #{{2}} has been confirmed!", "footer_content": "Thank you for shopping with us", "buttons": [ { "type": "URL", "text": "Track Order", "url": "https://example.com/track/{{1}}" } ], "sample_values": [], "add_security_recommendation": false, "code_expiration_minutes": 0, "quality_rating": "UNKNOWN", "created_by_name": "Jane Admin", "updated_by_name": "Jane Admin", "created_at": "2024-01-01T00:00:00Z", "updated_at": "2024-01-01T00:00:00Z" } ], "total": 50, "page": 1, "limit": 50 }}Get Template
Section titled “Get Template”Retrieve a single template by ID. Returns the same object shape as a list item.
GET /api/templates/{id}Create Template
Section titled “Create Template”Create a new template locally. Creating does not submit it to Meta — call Submit Template for that.
POST /api/templatesRequest Body
Section titled “Request Body”{ "whatsapp_account": "Main Business", "name": "welcome_message", "display_name": "Welcome Message", "language": "en", "category": "MARKETING", "header_type": "TEXT", "header_content": "Welcome!", "body_content": "Welcome to our store, {{1}}! Use code {{2}} for 10% off your first order.", "footer_content": "Reply STOP to unsubscribe", "buttons": [], "sample_values": ["John", "SAVE10"]}| Field | Type | Required | Description |
|---|---|---|---|
whatsapp_account | string | Yes | Account name |
name | string | Yes | Meta template name (lowercase, underscores) |
language | string | Yes | Language code, e.g. en |
category | string | Yes | MARKETING, UTILITY, or AUTHENTICATION |
display_name | string | No | Friendly label shown in the UI |
header_type | string | No | TEXT, IMAGE, DOCUMENT, VIDEO, or NONE |
header_content | string | No | Header text when header_type is TEXT |
body_content | string | No | Body text with {{1}}-style or named placeholders |
footer_content | string | No | Footer text |
buttons | array | No | Button definitions |
sample_values | array | No | Example values Meta uses during review |
add_security_recommendation | boolean | No | AUTHENTICATION templates — appends Meta's security line |
code_expiration_minutes | integer | No | AUTHENTICATION templates — 1–90; 0 omits the expiry footer |
Update Template
Section titled “Update Template”Update an existing template. Accepts the same body as Create.
PUT /api/templates/{id}Delete Template
Section titled “Delete Template”Delete a template.
DELETE /api/templates/{id}Sync Templates
Section titled “Sync Templates”Pull templates from Meta for one account and upsert them locally (matching on account + name +
language, restoring soft-deleted rows). Requires templates:sync.
POST /api/templates/syncThe account name can be given either as an ?account= query parameter or in the body:
{ "whatsapp_account": "Main Business"}Omitting it returns 400 whatsapp_account is required; an unknown name returns 404. If Meta
cannot be reached, the endpoint returns 502.
Submit Template
Section titled “Submit Template”Submit a template for Meta approval.
POST /api/templates/{id}/publishResponse
Section titled “Response”{ "status": "success", "data": { "id": "uuid", "status": "PENDING" }}Upload Template Media
Section titled “Upload Template Media”Upload a media asset (image, video, or PDF) for a template's media header. This
performs a resumable upload to Meta and returns a handle that you embed in
the HEADER component's example when creating the template.
POST /api/templates/upload-mediaSend the request as multipart/form-data:
| Field | Location | Required | Description |
|---|---|---|---|
account | form field or ?account= query | Yes | Name of the WhatsApp account. The account must have an app_id configured. |
file | form file | Yes | The media file to upload (image/jpeg, image/png, video/mp4, or application/pdf). |
curl -X POST "http://your-server:8080/api/templates/upload-media?account=main" \ -H "X-API-Key: whm_your_api_key" \ -F "file=@header.jpg"Response
Section titled “Response”{ "status": "success", "data": { "handle": "4::aW1hZ2UvanBlZw==:...", "filename": "header.jpg", "mime_type": "image/jpeg", "size": 24576 }}Set the returned handle as header_content when creating a template whose header_type is
IMAGE, VIDEO or DOCUMENT — Whatomate wraps it into Meta's
example.header_handle on submission:
{ "header_type": "IMAGE", "header_content": "4::aW1hZ2UvanBlZw==:..."}Template Parts
Section titled “Template Parts”Meta's four components map onto flat fields in the Whatomate API:
| Meta component | Whatomate fields |
|---|---|
HEADER | header_type (TEXT | IMAGE | DOCUMENT | VIDEO | NONE) + header_content |
BODY | body_content |
FOOTER | footer_content |
BUTTONS | buttons |
Whatomate assembles the Meta components payload itself when you submit the template.
Template Variables
Section titled “Template Variables”Positional Parameters
Section titled “Positional Parameters”Use {{1}}, {{2}}, etc. for dynamic content:
Hello {{1}}, your order #{{2}} is ready for pickup at {{3}}.Provide sample values as objects keyed by component + index:
{ "body_content": "Hello {{1}}, your order #{{2}} is ready!", "sample_values": [ { "component": "body", "index": 1, "value": "John" }, { "component": "body", "index": 2, "value": "12345" } ]}Named Parameters
Section titled “Named Parameters”Templates also support named parameters for better readability:
Hello {{customer_name}}, your order #{{order_id}} is ready for pickup at {{store_location}}.When using named parameters, provide sample values with param_name:
{ "body_content": "Hello {{customer_name}}, your order #{{order_id}} is ready!", "sample_values": [ { "component": "body", "param_name": "customer_name", "value": "John" }, { "component": "body", "param_name": "order_id", "value": "12345" } ]}You do not set parameter_format yourself — Whatomate detects non-numeric placeholders and sends
parameter_format: "NAMED" to Meta on submission.
URL Button Parameters
Section titled “URL Button Parameters”Templates can include URL buttons with dynamic variables. For example, a "Track Order" button with URL https://example.com/track/{{1}}:
{ "type": "BUTTONS", "buttons": [ { "type": "URL", "text": "Track Order", "url": "https://example.com/track/{{1}}", "example": "https://example.com/track/12345" } ]}When sending a template with dynamic URL buttons, provide the dynamic values via the button_params field in the Send Template Message endpoint. The key is the zero-based button index:
{ "template_name": "order_shipped", "template_params": { "1": "John", "2": "12345" }, "button_params": { "0": "12345" }}