curl --request POST \
--url https://api.social-api.ai/v1/platforms/whatsapp/accounts/{id}/templates \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"category": "UTILITY",
"components": [
{
"buttons": [
{
"example": {},
"phone_number": "+15551234567",
"text": "Visit",
"type": "URL",
"url": "https://example.com/{{1}}"
}
],
"example": {},
"format": "TEXT",
"text": "Hello {{1}}, your order {{2}} is confirmed.",
"type": "BODY"
}
],
"language": "en_US",
"name": "order_confirmation"
}
'import requests
url = "https://api.social-api.ai/v1/platforms/whatsapp/accounts/{id}/templates"
payload = {
"category": "UTILITY",
"components": [
{
"buttons": [
{
"example": {},
"phone_number": "+15551234567",
"text": "Visit",
"type": "URL",
"url": "https://example.com/{{1}}"
}
],
"example": {},
"format": "TEXT",
"text": "Hello {{1}}, your order {{2}} is confirmed.",
"type": "BODY"
}
],
"language": "en_US",
"name": "order_confirmation"
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
category: 'UTILITY',
components: [
{
buttons: [
{
example: {},
phone_number: '+15551234567',
text: 'Visit',
type: 'URL',
url: 'https://example.com/{{1}}'
}
],
example: {},
format: 'TEXT',
text: 'Hello {{1}}, your order {{2}} is confirmed.',
type: 'BODY'
}
],
language: 'en_US',
name: 'order_confirmation'
})
};
fetch('https://api.social-api.ai/v1/platforms/whatsapp/accounts/{id}/templates', 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.social-api.ai/v1/platforms/whatsapp/accounts/{id}/templates",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'category' => 'UTILITY',
'components' => [
[
'buttons' => [
[
'example' => [
],
'phone_number' => '+15551234567',
'text' => 'Visit',
'type' => 'URL',
'url' => 'https://example.com/{{1}}'
]
],
'example' => [
],
'format' => 'TEXT',
'text' => 'Hello {{1}}, your order {{2}} is confirmed.',
'type' => 'BODY'
]
],
'language' => 'en_US',
'name' => 'order_confirmation'
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.social-api.ai/v1/platforms/whatsapp/accounts/{id}/templates"
payload := strings.NewReader("{\n \"category\": \"UTILITY\",\n \"components\": [\n {\n \"buttons\": [\n {\n \"example\": {},\n \"phone_number\": \"+15551234567\",\n \"text\": \"Visit\",\n \"type\": \"URL\",\n \"url\": \"https://example.com/{{1}}\"\n }\n ],\n \"example\": {},\n \"format\": \"TEXT\",\n \"text\": \"Hello {{1}}, your order {{2}} is confirmed.\",\n \"type\": \"BODY\"\n }\n ],\n \"language\": \"en_US\",\n \"name\": \"order_confirmation\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
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.social-api.ai/v1/platforms/whatsapp/accounts/{id}/templates")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"category\": \"UTILITY\",\n \"components\": [\n {\n \"buttons\": [\n {\n \"example\": {},\n \"phone_number\": \"+15551234567\",\n \"text\": \"Visit\",\n \"type\": \"URL\",\n \"url\": \"https://example.com/{{1}}\"\n }\n ],\n \"example\": {},\n \"format\": \"TEXT\",\n \"text\": \"Hello {{1}}, your order {{2}} is confirmed.\",\n \"type\": \"BODY\"\n }\n ],\n \"language\": \"en_US\",\n \"name\": \"order_confirmation\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.social-api.ai/v1/platforms/whatsapp/accounts/{id}/templates")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"category\": \"UTILITY\",\n \"components\": [\n {\n \"buttons\": [\n {\n \"example\": {},\n \"phone_number\": \"+15551234567\",\n \"text\": \"Visit\",\n \"type\": \"URL\",\n \"url\": \"https://example.com/{{1}}\"\n }\n ],\n \"example\": {},\n \"format\": \"TEXT\",\n \"text\": \"Hello {{1}}, your order {{2}} is confirmed.\",\n \"type\": \"BODY\"\n }\n ],\n \"language\": \"en_US\",\n \"name\": \"order_confirmation\"\n}"
response = http.request(request)
puts response.read_body{
"category": "UTILITY",
"id": "1234567890123456",
"status": "PENDING"
}{
"error": {
"code": "resource.not_found",
"message": "Account not found",
"meta": {}
}
}{
"error": {
"code": "resource.not_found",
"message": "Account not found",
"meta": {}
}
}{
"error": {
"code": "resource.not_found",
"message": "Account not found",
"meta": {}
}
}{
"error": {
"code": "resource.not_found",
"message": "Account not found",
"meta": {}
}
}{
"error": {
"code": "resource.not_found",
"message": "Account not found",
"meta": {}
}
}Create a message template
Submits a new message template to the WhatsApp Business Account (WABA) for review. The request body is the raw WhatsApp Cloud API template payload (name, category, language, components). New templates start in PENDING status; Meta reviews them and the status transitions to APPROVED or REJECTED asynchronously.
curl --request POST \
--url https://api.social-api.ai/v1/platforms/whatsapp/accounts/{id}/templates \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"category": "UTILITY",
"components": [
{
"buttons": [
{
"example": {},
"phone_number": "+15551234567",
"text": "Visit",
"type": "URL",
"url": "https://example.com/{{1}}"
}
],
"example": {},
"format": "TEXT",
"text": "Hello {{1}}, your order {{2}} is confirmed.",
"type": "BODY"
}
],
"language": "en_US",
"name": "order_confirmation"
}
'import requests
url = "https://api.social-api.ai/v1/platforms/whatsapp/accounts/{id}/templates"
payload = {
"category": "UTILITY",
"components": [
{
"buttons": [
{
"example": {},
"phone_number": "+15551234567",
"text": "Visit",
"type": "URL",
"url": "https://example.com/{{1}}"
}
],
"example": {},
"format": "TEXT",
"text": "Hello {{1}}, your order {{2}} is confirmed.",
"type": "BODY"
}
],
"language": "en_US",
"name": "order_confirmation"
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
category: 'UTILITY',
components: [
{
buttons: [
{
example: {},
phone_number: '+15551234567',
text: 'Visit',
type: 'URL',
url: 'https://example.com/{{1}}'
}
],
example: {},
format: 'TEXT',
text: 'Hello {{1}}, your order {{2}} is confirmed.',
type: 'BODY'
}
],
language: 'en_US',
name: 'order_confirmation'
})
};
fetch('https://api.social-api.ai/v1/platforms/whatsapp/accounts/{id}/templates', 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.social-api.ai/v1/platforms/whatsapp/accounts/{id}/templates",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'category' => 'UTILITY',
'components' => [
[
'buttons' => [
[
'example' => [
],
'phone_number' => '+15551234567',
'text' => 'Visit',
'type' => 'URL',
'url' => 'https://example.com/{{1}}'
]
],
'example' => [
],
'format' => 'TEXT',
'text' => 'Hello {{1}}, your order {{2}} is confirmed.',
'type' => 'BODY'
]
],
'language' => 'en_US',
'name' => 'order_confirmation'
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.social-api.ai/v1/platforms/whatsapp/accounts/{id}/templates"
payload := strings.NewReader("{\n \"category\": \"UTILITY\",\n \"components\": [\n {\n \"buttons\": [\n {\n \"example\": {},\n \"phone_number\": \"+15551234567\",\n \"text\": \"Visit\",\n \"type\": \"URL\",\n \"url\": \"https://example.com/{{1}}\"\n }\n ],\n \"example\": {},\n \"format\": \"TEXT\",\n \"text\": \"Hello {{1}}, your order {{2}} is confirmed.\",\n \"type\": \"BODY\"\n }\n ],\n \"language\": \"en_US\",\n \"name\": \"order_confirmation\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
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.social-api.ai/v1/platforms/whatsapp/accounts/{id}/templates")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"category\": \"UTILITY\",\n \"components\": [\n {\n \"buttons\": [\n {\n \"example\": {},\n \"phone_number\": \"+15551234567\",\n \"text\": \"Visit\",\n \"type\": \"URL\",\n \"url\": \"https://example.com/{{1}}\"\n }\n ],\n \"example\": {},\n \"format\": \"TEXT\",\n \"text\": \"Hello {{1}}, your order {{2}} is confirmed.\",\n \"type\": \"BODY\"\n }\n ],\n \"language\": \"en_US\",\n \"name\": \"order_confirmation\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.social-api.ai/v1/platforms/whatsapp/accounts/{id}/templates")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"category\": \"UTILITY\",\n \"components\": [\n {\n \"buttons\": [\n {\n \"example\": {},\n \"phone_number\": \"+15551234567\",\n \"text\": \"Visit\",\n \"type\": \"URL\",\n \"url\": \"https://example.com/{{1}}\"\n }\n ],\n \"example\": {},\n \"format\": \"TEXT\",\n \"text\": \"Hello {{1}}, your order {{2}} is confirmed.\",\n \"type\": \"BODY\"\n }\n ],\n \"language\": \"en_US\",\n \"name\": \"order_confirmation\"\n}"
response = http.request(request)
puts response.read_body{
"category": "UTILITY",
"id": "1234567890123456",
"status": "PENDING"
}{
"error": {
"code": "resource.not_found",
"message": "Account not found",
"meta": {}
}
}{
"error": {
"code": "resource.not_found",
"message": "Account not found",
"meta": {}
}
}{
"error": {
"code": "resource.not_found",
"message": "Account not found",
"meta": {}
}
}{
"error": {
"code": "resource.not_found",
"message": "Account not found",
"meta": {}
}
}{
"error": {
"code": "resource.not_found",
"message": "Account not found",
"meta": {}
}
}Authorizations
Prefix your API key with "Bearer ". Example: Authorization: Bearer sapi_key_...
Path Parameters
Connected account ID (sapi_acc_...)
Body
Template definition
Category is the message category. Marketing intent in a UTILITY template triggers automatic rejection.
MARKETING, UTILITY, AUTHENTICATION "UTILITY"
Components define the template body, optional header, optional footer, and optional buttons. At minimum one BODY component is required.
Show child attributes
Show child attributes
Language is the BCP-47 language code (e.g. en_US, fr_FR, pt_BR).
"en_US"
Name is the template identifier. Lowercase letters, digits, underscores only; no spaces.
"order_confirmation"