Templates
Create Template
Submit a WhatsApp template to Meta for approval ⏳
POST
/
v1
/
businesses
/
{businessId}
/
create
/
template
Create Template
curl --request POST \
--url https://api.example.com/v1/businesses/{businessId}/create/templateimport requests
url = "https://api.example.com/v1/businesses/{businessId}/create/template"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.example.com/v1/businesses/{businessId}/create/template', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v1/businesses/{businessId}/create/template",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v1/businesses/{businessId}/create/template"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/v1/businesses/{businessId}/create/template")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/businesses/{businessId}/create/template")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_bodySubmit a new WhatsApp template to Meta for review. Templates cannot be used until Meta approves them — typically within 5 minutes but up to 24 hours. Check approval status using Get templates.
The template starts with
Endpoint
POST https://api.connectly.ai/v1/businesses/{businessId}/create/template
Request body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Template name. Used to reference the template when sending messages. |
language | object | Yes | Language object with a single code field (e.g. { "code": "en_US" }). See Meta’s supported languages. |
category | string | Yes | Template category: MESSAGE_TEMPLATE_GROUP_CATEGORY_MARKETING, MESSAGE_TEMPLATE_GROUP_CATEGORY_UTILITY, or MESSAGE_TEMPLATE_GROUP_CATEGORY_AUTHENTICATION. |
template_components | array | Yes | Ordered list of component objects defining the template structure. See Template components. |
Response
{
"entity": {
"id": "template_name",
"name": "template_name",
"category": "MARKETING",
"templates": [
{
"id": "1385622408844485",
"language": { "code": "en_US" },
"status": "MESSAGE_TEMPLATE_STATUS_PENDING",
"createdAt": "2023-01-18T01:07:20.075195879Z",
"updatedAt": "2023-01-18T01:07:20.075195879Z",
"templateComponents": [...],
"rejectionReason": null
}
]
}
}
status: MESSAGE_TEMPLATE_STATUS_PENDING. Once Meta reviews it, the status transitions to approved or rejected.
Examples
Body only — no variables
Body only — no variables
{
"name": "simple_greeting",
"language": { "code": "en_US" },
"template_components": [
{
"body": {
"text": { "text": "Thanks for reaching out! We'll be in touch shortly." }
}
}
]
}
Body with variables
Body with variables
Variables use
{{N}} syntax, numbered sequentially from 1.{
"name": "order_confirmation",
"language": { "code": "en_US" },
"template_components": [
{
"body": {
"text": {
"text": "Hi {{1}}, your order {{2}} has been confirmed and will arrive by {{3}}."
}
}
}
]
}
Image header + body variables
Image header + body variables
Provide an example image URL in
example to speed up Meta’s approval review.{
"name": "product_launch",
"language": { "code": "en_US" },
"template_components": [
{
"header": {
"media": {
"type": "TYPE_IMAGE",
"example": ["https://cdn.connectly.ai/example/product.png"]
}
}
},
{
"body": {
"text": {
"text": "Hi {{1}}, check out our new product — {{2}}. Available now!"
}
}
}
]
}
Text header + body + footer
Text header + body + footer
Text headers support one variable (
{{1}}).{
"name": "appointment_reminder",
"language": { "code": "en_US" },
"template_components": [
{
"header": {
"text": { "text": "Reminder: {{1}}" }
}
},
{
"body": {
"text": { "text": "Your appointment is scheduled for {{1}} at {{2}}." }
}
},
{
"footer": {
"text": { "text": "Reply CANCEL to cancel." }
}
}
]
}
Document header + footer
Document header + footer
{
"name": "invoice_template",
"language": { "code": "en_US" },
"template_components": [
{
"header": {
"media": {
"type": "TYPE_DOCUMENT",
"example": ["https://cdn.connectly.ai/example/invoice.pdf"]
}
}
},
{
"body": {
"text": { "text": "Please find your invoice attached." }
}
},
{
"footer": {
"text": { "text": "Contact support@example.com for questions." }
}
}
]
}
Quick reply buttons
Quick reply buttons
Up to 3 quick reply buttons. Cannot be combined with URL or phone buttons.
{
"name": "confirm_appointment",
"language": { "code": "en_US" },
"template_components": [
{
"body": {
"text": { "text": "Can you make your appointment on {{1}}?" }
}
},
{ "button": { "quickReply": { "text": "Confirm" } } },
{ "button": { "quickReply": { "text": "Reschedule" } } },
{ "button": { "quickReply": { "text": "Cancel" } } }
]
}
URL button
URL button
Do not use shortened URLs — WhatsApp rejects them. You can add a dynamic suffix variable to the URL.
{
"name": "track_order",
"language": { "code": "en_US" },
"template_components": [
{
"body": {
"text": { "text": "Your order is on its way! Track it here:" }
}
},
{
"button": {
"url": {
"text": "Track my order",
"url": "https://example.com/track/{{1}}"
}
}
}
]
}
Phone number button
Phone number button
{
"name": "contact_support",
"language": { "code": "en_US" },
"template_components": [
{
"body": {
"text": { "text": "Need help? Call our support team directly." }
}
},
{
"button": {
"phoneNumber": {
"text": "Call support",
"phoneNumber": "+16044441234"
}
}
}
]
}
Carousel template
Carousel template
Carousel templates display multiple horizontally scrollable cards. Each card has its own header image, body, and buttons.To send this carousel template, see Send template message — Carousel.
{
"name": "carousel_demo_1",
"language": { "code": "en_US" },
"category": "MESSAGE_TEMPLATE_GROUP_CATEGORY_MARKETING",
"template_components": [
{
"body": {
"text": {
"text": "Hey there! 👋 Check out our latest products."
}
}
},
{
"carousel": {
"cards": [
{
"components": [
{
"header": {
"media": {
"type": "TYPE_IMAGE",
"example": ["https://example.com/card1.png"]
}
}
},
{
"body": {
"text": {
"text": "Perfect for you, {{1}}! 🍓"
}
}
},
{
"button": {
"url": {
"text": "Shop now",
"url": "https://example.com/store/{{1}}"
}
}
},
{
"button": {
"quickReply": { "text": "See more" }
}
}
]
},
{
"components": [
{
"header": {
"media": {
"type": "TYPE_IMAGE",
"example": ["https://example.com/card2.png"]
}
}
},
{
"body": {
"text": {
"text": "Unlock coupons for just {{1}}! 🎉"
}
}
},
{
"button": {
"url": {
"text": "Get coupons",
"url": "https://example.com/coupons/{{1}}"
}
}
},
{
"button": {
"quickReply": { "text": "Explore more" }
}
}
]
}
]
}
}
]
}
Was this page helpful?
⌘I
