curl --request POST \
--url https://api.social-api.ai/v1/platforms/whatsapp/templates/validate \
--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/templates/validate"
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/templates/validate', 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/templates/validate",
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/templates/validate"
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/templates/validate")
.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/templates/validate")
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{
"errors": [
{
"component_index": 0,
"field": "name",
"message": "name must contain only lowercase letters, digits, and underscores (no spaces or capitals)"
}
],
"valid": true,
"warnings": [
{
"component_index": 0,
"field": "name",
"message": "name must contain only lowercase letters, digits, and underscores (no spaces or capitals)"
}
]
}{
"error": {
"code": "resource.not_found",
"message": "Account not found",
"meta": {}
}
}{
"error": {
"code": "resource.not_found",
"message": "Account not found",
"meta": {}
}
}Validate a message template
Dry-run validation of a WhatsApp message template against the Cloud API rules (name format, component cardinality, header format, text limits, placeholder sequencing, button constraints). Returns errors for hard violations that WhatsApp would reject and warnings for best-practice issues. Performs no network call and does not submit the template.
curl --request POST \
--url https://api.social-api.ai/v1/platforms/whatsapp/templates/validate \
--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/templates/validate"
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/templates/validate', 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/templates/validate",
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/templates/validate"
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/templates/validate")
.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/templates/validate")
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{
"errors": [
{
"component_index": 0,
"field": "name",
"message": "name must contain only lowercase letters, digits, and underscores (no spaces or capitals)"
}
],
"valid": true,
"warnings": [
{
"component_index": 0,
"field": "name",
"message": "name must contain only lowercase letters, digits, and underscores (no spaces or capitals)"
}
]
}{
"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_...
Body
Template definition to validate
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"
Response
Validation result
Errors are hard violations WhatsApp would reject at submission.
Show child attributes
Show child attributes
Valid is true when there are no errors (warnings do not affect validity).
Warnings are best-practice issues or items that cannot be fully verified offline.
Show child attributes
Show child attributes