Skip to content
View as Markdown
ReferenceTemplates

Templates

Manage WhatsApp message templates

DevelopersUpdated

WhatsApp Message Templates are pre-approved message formats required for sending business-initiated messages. Templates must be approved by Meta before use.

Retrieve all templates for your account.

GET/api/templates
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.

{
"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
}
}

Retrieve a single template by ID. Returns the same object shape as a list item.

GET/api/templates/{id}

Create a new template locally. Creating does not submit it to Meta — call Submit Template for that.

POST/api/templates
{
"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 an existing template. Accepts the same body as Create.

PUT/api/templates/{id}

Delete a template.

DELETE/api/templates/{id}

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/sync

The 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 a template for Meta approval.

POST/api/templates/{id}/publish
{
"status": "success",
"data": {
"id": "uuid",
"status": "PENDING"
}
}

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-media

Send 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).
Terminal window
curl -X POST "http://your-server:8080/api/templates/upload-media?account=main" \
-H "X-API-Key: soosh_your_api_key" \
{
"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 — Soosh wraps it into Meta’s example.header_handle on submission:

{
"header_type": "IMAGE",
"header_content": "4::aW1hZ2UvanBlZw==:..."
}

Meta’s four components map onto flat fields in the Soosh API:

Meta component Soosh fields
HEADER header_type (TEXT | IMAGE | DOCUMENT | VIDEO | NONE) + header_content
BODY body_content
FOOTER footer_content
BUTTONS buttons

Soosh assembles the Meta components payload itself when you submit the template.

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" }
]
}

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 — Soosh detects non-numeric placeholders and sends parameter_format: "NAMED" to Meta on submission.

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" }
}