Send Template Message (Phone Number)
curl --request POST \
--url https://lancepilot.com/api/v3/workspaces/{workspace}/contacts/number/{number}/template-messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"template_id": 123,
"template_data": {
"header": {
"variables": [
"Premium Member"
],
"file": "https://example.com/product-image.jpg"
},
"buttons": [
{
"type": "URL",
"variables": [
"promo-code-2025"
]
}
]
}
}
'import requests
url = "https://lancepilot.com/api/v3/workspaces/{workspace}/contacts/number/{number}/template-messages"
payload = {
"template_id": 123,
"template_data": {
"header": {
"variables": ["Premium Member"],
"file": "https://example.com/product-image.jpg"
},
"buttons": [
{
"type": "URL",
"variables": ["promo-code-2025"]
}
]
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
template_id: 123,
template_data: {
header: {variables: ['Premium Member'], file: 'https://example.com/product-image.jpg'},
buttons: [{type: 'URL', variables: ['promo-code-2025']}]
}
})
};
fetch('https://lancepilot.com/api/v3/workspaces/{workspace}/contacts/number/{number}/template-messages', 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://lancepilot.com/api/v3/workspaces/{workspace}/contacts/number/{number}/template-messages",
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([
'template_id' => 123,
'template_data' => [
'header' => [
'variables' => [
'Premium Member'
],
'file' => 'https://example.com/product-image.jpg'
],
'buttons' => [
[
'type' => 'URL',
'variables' => [
'promo-code-2025'
]
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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://lancepilot.com/api/v3/workspaces/{workspace}/contacts/number/{number}/template-messages"
payload := strings.NewReader("{\n \"template_id\": 123,\n \"template_data\": {\n \"header\": {\n \"variables\": [\n \"Premium Member\"\n ],\n \"file\": \"https://example.com/product-image.jpg\"\n },\n \"buttons\": [\n {\n \"type\": \"URL\",\n \"variables\": [\n \"promo-code-2025\"\n ]\n }\n ]\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://lancepilot.com/api/v3/workspaces/{workspace}/contacts/number/{number}/template-messages")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"template_id\": 123,\n \"template_data\": {\n \"header\": {\n \"variables\": [\n \"Premium Member\"\n ],\n \"file\": \"https://example.com/product-image.jpg\"\n },\n \"buttons\": [\n {\n \"type\": \"URL\",\n \"variables\": [\n \"promo-code-2025\"\n ]\n }\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://lancepilot.com/api/v3/workspaces/{workspace}/contacts/number/{number}/template-messages")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"template_id\": 123,\n \"template_data\": {\n \"header\": {\n \"variables\": [\n \"Premium Member\"\n ],\n \"file\": \"https://example.com/product-image.jpg\"\n },\n \"buttons\": [\n {\n \"type\": \"URL\",\n \"variables\": [\n \"promo-code-2025\"\n ]\n }\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"status": 201,
"message": "Resource created successfully.",
"data": {}
}{
"message": "Only template messages are allowed for this contact"
}{
"message": "Unauthenticated."
}{
"message": "Template not found"
}{
"message": "Invalid Number",
"errors": {
"body.variables": [
"The body.variables field is required."
]
}
}{
"message": "Failed to send message"
}Send Template Messages
Send Template Message (Number)
Send a WhatsApp template message to a contact using their phone number. If the contact doesn’t exist, it will be automatically created. Templates can include text/media headers, body with variables, footers, and buttons.
POST
/
workspaces
/
{workspace}
/
contacts
/
number
/
{number}
/
template-messages
Send Template Message (Phone Number)
curl --request POST \
--url https://lancepilot.com/api/v3/workspaces/{workspace}/contacts/number/{number}/template-messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"template_id": 123,
"template_data": {
"header": {
"variables": [
"Premium Member"
],
"file": "https://example.com/product-image.jpg"
},
"buttons": [
{
"type": "URL",
"variables": [
"promo-code-2025"
]
}
]
}
}
'import requests
url = "https://lancepilot.com/api/v3/workspaces/{workspace}/contacts/number/{number}/template-messages"
payload = {
"template_id": 123,
"template_data": {
"header": {
"variables": ["Premium Member"],
"file": "https://example.com/product-image.jpg"
},
"buttons": [
{
"type": "URL",
"variables": ["promo-code-2025"]
}
]
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
template_id: 123,
template_data: {
header: {variables: ['Premium Member'], file: 'https://example.com/product-image.jpg'},
buttons: [{type: 'URL', variables: ['promo-code-2025']}]
}
})
};
fetch('https://lancepilot.com/api/v3/workspaces/{workspace}/contacts/number/{number}/template-messages', 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://lancepilot.com/api/v3/workspaces/{workspace}/contacts/number/{number}/template-messages",
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([
'template_id' => 123,
'template_data' => [
'header' => [
'variables' => [
'Premium Member'
],
'file' => 'https://example.com/product-image.jpg'
],
'buttons' => [
[
'type' => 'URL',
'variables' => [
'promo-code-2025'
]
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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://lancepilot.com/api/v3/workspaces/{workspace}/contacts/number/{number}/template-messages"
payload := strings.NewReader("{\n \"template_id\": 123,\n \"template_data\": {\n \"header\": {\n \"variables\": [\n \"Premium Member\"\n ],\n \"file\": \"https://example.com/product-image.jpg\"\n },\n \"buttons\": [\n {\n \"type\": \"URL\",\n \"variables\": [\n \"promo-code-2025\"\n ]\n }\n ]\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://lancepilot.com/api/v3/workspaces/{workspace}/contacts/number/{number}/template-messages")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"template_id\": 123,\n \"template_data\": {\n \"header\": {\n \"variables\": [\n \"Premium Member\"\n ],\n \"file\": \"https://example.com/product-image.jpg\"\n },\n \"buttons\": [\n {\n \"type\": \"URL\",\n \"variables\": [\n \"promo-code-2025\"\n ]\n }\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://lancepilot.com/api/v3/workspaces/{workspace}/contacts/number/{number}/template-messages")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"template_id\": 123,\n \"template_data\": {\n \"header\": {\n \"variables\": [\n \"Premium Member\"\n ],\n \"file\": \"https://example.com/product-image.jpg\"\n },\n \"buttons\": [\n {\n \"type\": \"URL\",\n \"variables\": [\n \"promo-code-2025\"\n ]\n }\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"status": 201,
"message": "Resource created successfully.",
"data": {}
}{
"message": "Only template messages are allowed for this contact"
}{
"message": "Unauthenticated."
}{
"message": "Template not found"
}{
"message": "Invalid Number",
"errors": {
"body.variables": [
"The body.variables field is required."
]
}
}{
"message": "Failed to send message"
}Description
This endpoint allows you to send WhatsApp template messages to a contact using their phone number. If the contact doesn’t exist in your workspace, it will be automatically created. Templates can include various components such as headers (text/media), body text with variables, footers, and buttons.Template Components
Templates may contain the following components:- Header: Text (with variables) or Media (image, video, document)
- Body: Message text with dynamic variables (
{{1}},{{2}}, etc.) - Footer: Static footer text
- Buttons: URL buttons (with variables), phone buttons, or quick reply buttons
Request Payload Structure
Basic Structure
{
"template_id": 123,
"template_data": {
"header": {
"variables": ["Header Variable"],
"file": "https://example.com/image.jpg"
},
"body": {
"variables": ["Variable 1", "Variable 2"]
},
"buttons": [
{
"type": "URL",
"variables": ["promo-code-123"]
}
]
}
}
Examples by Template Type
1. Simple Body-Only Template
For templates with only body text and no variables:{
"template_id": 123,
"template_data": {}
}
2. Body with Variables
Template body:"Hello \{\{1\}\}, your order \{\{2\}\} is confirmed!"
{
"template_id": 123,
"template_data": {
"body": {
"variables": ["John Doe", "#12345"]
}
}
}
- Maximum 20 variables in body
- Each variable max 1000 characters
- Total body length (with variables) max 1024 characters
- Authentication templates: variables max 11 characters, no links allowed
3. Text Header with Variables
Template header:"Welcome \{\{1\}\}!"
{
"template_id": 123,
"template_data": {
"header": {
"variables": ["Premium Member"]
},
"body": {
"variables": ["John", "Gold Tier"]
}
}
}
- Maximum 1 variable in text header
- Variable max 60 characters
- Total header length (with variables) max 60 characters
4. Image Header Template
Option A: Using Image URL (JSON)
{
"template_id": 123,
"template_data": {
"header": {
"file": "https://example.com/product-image.jpg"
},
"body": {
"variables": ["Product Name", "$99.99"]
}
}
}
Option B: Uploading Image File (multipart/form-data)
POST /api/v3/workspaces/{workspace}/contacts/number/{number}/template-messages
Content-Type: multipart/form-data
template_id: 123
template_data[header][file]: [binary image file]
template_data[body][variables][0]: Product Name
template_data[body][variables][1]: $99.99
- Allowed types: jpg, jpeg, png
- Maximum size: 5 MB (5120 KB)
5. Video Header Template
Using Video URL
{
"template_id": 123,
"template_data": {
"header": {
"file": "https://example.com/demo-video.mp4"
},
"body": {
"variables": ["John", "Premium Course"]
}
}
}
Uploading Video File
POST /api/v3/workspaces/{workspace}/contacts/number/{number}/template-messages
Content-Type: multipart/form-data
template_id: 123
template_data[header][file]: [binary video file]
template_data[body][variables][0]: John
template_data[body][variables][1]: Premium Course
- Allowed type: video/mp4
- Maximum size: 16 MB (16384 KB)
6. Document Header Template
Using Document URL
{
"template_id": 123,
"template_data": {
"header": {
"file": "https://example.com/invoice.pdf"
},
"body": {
"variables": ["Invoice #12345", "$500.00"]
}
}
}
Uploading Document File
POST /api/v3/workspaces/{workspace}/contacts/number/{number}/template-messages
Content-Type: multipart/form-data
template_id: 123
template_data[header][file]: [binary PDF file]
template_data[body][variables][0]: Invoice #12345
template_data[body][variables][1]: $500.00
- Allowed type: application/pdf
- Maximum size: 30 MB (30720 KB)
7. Authentication/OTP Template
For one-time password templates:{
"template_id": 123,
"template_data": {
"body": {
"variables": ["123456"]
}
}
}
- Variables max 11 characters
- No links allowed in variables
8. URL Button with Variables
Template with dynamic URL button:https://example.com/promo/\{\{1\}\}
{
"template_id": 123,
"template_data": {
"body": {
"variables": ["John", "SAVE20"]
},
"buttons": [
{
"type": "URL",
"variables": ["SAVE20"]
}
]
}
}
- Each URL button variable max 2000 characters
- Number of variables must match template definition
9. Multiple URL Buttons with Variables
For templates with multiple URL buttons:{
"template_id": 123,
"template_data": {
"body": {
"variables": ["Order #12345"]
},
"buttons": [
{
"type": "URL",
"variables": ["12345"]
},
{
"type": "URL",
"variables": ["track-code-xyz"]
}
]
}
}
10. Complex Template (All Components)
Image header + body variables + URL button with variable:{
"template_id": 123,
"template_data": {
"header": {
"file": "https://example.com/banner.jpg"
},
"body": {
"variables": ["John Doe", "Premium Plan", "$99.99", "December 31, 2025"]
},
"buttons": [
{
"type": "URL",
"variables": ["user-123-token-abc"]
}
]
}
}
Phone Number Format
The phone number in the URL should be in international format without the+ symbol:
- ✅ Correct:
14155552671(USA),447911123456(UK),919876543210(India) - ❌ Incorrect:
+14155552671,+44 7911 123456,(415) 555-2671
Media File Requirements
Image Header
- Required: When template has image header
- Allowed types: jpg, jpeg, png
- Maximum size: 5 MB (5120 KB)
Video Header
- Required: When template has video header
- Allowed type: mp4
- Maximum size: 16 MB (16384 KB)
Document Header
- Required: When template has document header
- Allowed type: PDF
- Maximum size: 30 MB (30720 KB)
Complete Example with cURL
# JSON request with image URL to a new contact
curl -X POST "https://lancepilot.com/api/v3/workspaces/123/contacts/number/14155552671/template-messages" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"template_id": 789,
"template_data": {
"header": {
"file": "https://example.com/product.jpg"
},
"body": {
"variables": ["John Doe", "Premium Package", "$149.99"]
},
"buttons": [
{
"type": "URL",
"variables": ["promo2025"]
}
]
}
}'
# Multipart form-data request with file upload
curl -X POST "https://lancepilot.com/api/v3/workspaces/123/contacts/number/447911123456/template-messages" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-F "template_id=789" \
-F "template_data[header][file]=@/path/to/image.jpg" \
-F "template_data[body][variables][0]=John Doe" \
-F "template_data[body][variables][1]=Premium Package" \
-F "template_data[body][variables][2]=$149.99" \
-F "template_data[buttons][0][type]=URL" \
-F "template_data[buttons][0][variables][0]=promo2025"
Auto-Contact Creation
When sending to a number that doesn’t exist in your workspace:- The system validates the phone number format
- Automatically creates a new contact with:
- Name: “Unknown” (can be updated later)
- WhatsApp number: The provided number
- Country: Auto-detected from phone number
- Timezone: Set based on country
- Sends the template message to the newly created contact
Error Responses
Invalid Phone Number
{
"message": "Invalid Number"
}
Invalid Template ID
{
"message": "Template not found"
}
Missing Required Variables
{
"message": "The body.variables field is required.",
"errors": {
"body.variables": ["The body.variables field is required."]
}
}
Variable Count Mismatch
{
"message": "The body.variables must have at least 3 items.",
"errors": {
"body.variables": ["The body.variables must have at least 3 items."]
}
}
Body Text Too Long
{
"message": "Message body with all variable values is too long, it can be max 1024 characters",
"errors": {
"body.text": ["Message body with all variable values is too long, it can be max 1024 characters"]
}
}
Invalid Media File
{
"message": "The header.file must be a file of type: jpg, jpeg, png.",
"errors": {
"header.file": ["The header.file must be a file of type: jpg, jpeg, png."]
}
}
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Path Parameters
ID of the workspace.
WhatsApp phone number in international format without + symbol (e.g., 14155552671 for US, 447911123456 for UK).
Pattern:
^[1-9][0-9]{7,14}$Example:
"14155552671"
Body
application/jsonmultipart/form-data