Skip to main content
POST
/
workspaces
/
{workspace}
/
templates
Create a template
curl --request POST \
  --url https://lancepilot.com/api/v3/workspaces/{workspace}/templates \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "name": "login_otp_template",
  "language": "en",
  "category": "MARKETING",
  "body": {
    "text": "<string>",
    "otp_code": "<string>",
    "variables": [
      "<string>"
    ]
  },
  "header": "<unknown>",
  "footer": "<string>",
  "buttons": [
    {
      "type": "URL",
      "text": "<string>",
      "phone_number": "<string>",
      "url": "<string>"
    }
  ],
  "unsubscribeButton": true,
  "blockButton": true
}
'

Overview

Create a new WhatsApp message template. Templates must be approved by Meta before they can be used to send messages.
Templates typically take 5-30 minutes for approval. Use the Sync endpoint to check approval status.

Request Body Schema

FieldTypeRequiredDescription
namestringYesUnique template name (only lowercase + underscores).
languagestringYesLanguage code (e.g., en, es, fr).
categorystringYesOne of: MARKETING, UTILITY, AUTHENTICATION.
headerobject/nullNoTemplate header. Can be null, text, or media (image/video/document).
bodyobjectYesMain message body. Supports variables ({{1}}, {{2}}).
body.textstringYesMessage text (max 1024 chars).
body.variablesarrayConditionalRequired if variables exist in text.
footerstringNoFooter text (max 60 chars, no emojis).
buttonsarrayNoInteractive buttons (URL, Phone, Quick Reply). Max 3.
unsubscribeButtonbooleanNoShow Unsubscribe button (MARKETING only).
blockButtonbooleanNoShow Block button (MARKETING only).
addSecurityRecommendationbooleanAuth onlyInclude security warning (AUTHENTICATION only).
codeExpirationMinutesintegerAuth onlyOTP validity period in minutes (1-1440, AUTHENTICATION only).
copyCodeButtonbooleanAuth onlyAdd one-tap copy button (AUTHENTICATION only).

Complete Examples

Example 1: Marketing Template with Image Header

{
  "name": "summer_sale_promo",
  "language": "en",
  "category": "MARKETING",
  "header": {
    "type": "media",
    "media": {
      "type": "image",
      "file": "<binary_file_data>"
    }
  },
  "body": {
    "text": "Hi {{1}}! 🎉\n\nOur Summer Sale is here! Get {{2}}% off on all items. Use code: {{3}}\n\nHurry, offer ends soon!",
    "variables": ["John", "30", "SUMMER30"]
  },
  "footer": "Terms and conditions apply",
  "buttons": [
    {
      "type": "URL",
      "text": "Shop Now",
      "url": "https://example.com/sale"
    }
  ],
  "unsubscribeButton": true
}

Example 2: Authentication (OTP) Template

{
  "name": "login_otp_verification",
  "language": "en",
  "category": "AUTHENTICATION",
  "addSecurityRecommendation": true,
  "codeExpirationMinutes": 10,
  "copyCodeButton": true
}
Authentication templates are auto-generated by Meta with standard security messaging. You only need to specify the three parameters above.

Example 3: Utility Template with Multiple Buttons

{
  "name": "order_confirmation",
  "language": "en",
  "category": "UTILITY",
  "header": {
    "type": "text",
    "text": {
      "content": "Order #{{1}}",
      "variables": ["12345"]
    }
  },
  "body": {
    "text": "Hi {{1}},\n\nYour order has been confirmed!\n\nOrder ID: {{2}}\nTotal: {{3}}\nDelivery: {{4}}",
    "variables": ["Sarah", "ORD-12345", "$99.99", "Dec 15, 2025"]
  },
  "footer": "Thank you for shopping with us",
  "buttons": [
    {
      "type": "URL",
      "text": "Track Order",
      "url": "https://example.com/track"
    },
    {
      "type": "PHONE_NUMBER",
      "text": "Contact Support",
      "phone_number": "+1234567890"
    },
    {
      "type": "QUICK_REPLY",
      "text": "Cancel Order"
    }
  ]
}

Example 4: Simple Text Template

{
  "name": "appointment_reminder",
  "language": "en",
  "category": "UTILITY",
  "body": {
    "text": "Reminder: Your appointment with {{1}} is scheduled for {{2}} at {{3}}. Please arrive 10 minutes early.",
    "variables": ["Dr. Smith", "December 15, 2025", "2:00 PM"]
  },
  "footer": "Reply CANCEL to reschedule"
}

Example 5: URL Button with Variable

{
  "name": "personalized_offer",
  "language": "en",
  "category": "MARKETING",
  "body": {
    "text": "Exclusive offer for {{1}}! Your discount code {{2}} is ready. Click below to redeem.",
    "variables": ["VIP Members", "VIP20"]
  },
  "buttons": [
    {
      "type": "URL",
      "text": "Redeem Now",
      "url": "https://example.com/offer?code={{1}}",
      "variables": ["VIP20"]
    }
  ]
}

Example 6: Video Header Template

{
  "name": "product_tutorial",
  "language": "en",
  "category": "MARKETING",
  "header": {
    "type": "media",
    "media": {
      "type": "video",
      "file": "<binary_video_data>"
    }
  },
  "body": {
    "text": "Watch this quick tutorial on {{1}}! Learn how to get the most out of your purchase in just {{2}} minutes.",
    "variables": ["our new feature", "5"]
  },
  "footer": "Need help? Contact support"
}

Example 7: Document Header Template

{
  "name": "invoice_delivery",
  "language": "en",
  "category": "UTILITY",
  "header": {
    "type": "media",
    "media": {
      "type": "document",
      "file": "<binary_pdf_data>"
    }
  },
  "body": {
    "text": "Dear {{1}},\n\nPlease find your invoice #{{2}} attached. Amount due: {{3}}\n\nPayment due: {{4}}",
    "variables": ["John Doe", "INV-001", "$150.00", "Dec 31, 2025"]
  },
  "footer": "Thank you for your business"
}

Validation Rules

  • Must be unique in workspace
  • Only lowercase letters and underscores
  • Examples: ✅ welcome_message, order_confirmation_v2
  • Invalid: ❌ WelcomeMessage, order-confirmation, template 1
Must be valid ISO language code:
  • English: en
  • Spanish: es
  • French: fr
  • German: de
  • Portuguese: pt
  • Arabic: ar
  • And more…
Text Header:
  • Max 60 characters
  • Max 1 variable: {{1}}
  • Cannot start/end with variable
  • Example: ✅ Welcome {{1}}
  • Invalid: ❌ {{1}} Welcome
Media Header:
  • Image: JPG/PNG, max 5MB (5120KB)
  • Video: MP4, max 10MB (10240KB)
  • Document: PDF, max 30MB (30720KB)
  • Required field
  • Max 1024 characters
  • Cannot start or end with variable
  • Max 2 consecutive newlines (\n\n allowed, \n\n\n not allowed)
  • Variables must match: if text has {{1}} and {{2}}, variables array must have exactly 2 items
  • Variables are numbered sequentially: {{1}}, {{2}}, {{3}}, etc.
  • Max 3 buttons total (unsubscribe/block don’t count toward limit)
  • URL Button:
    • Requires text and url
    • Can have 1 variable at end: https://example.com/page?id={{1}}
    • Variable must be in variables array
  • PHONE_NUMBER Button:
    • Requires text and phone_number
    • Phone must include country code: +1234567890
  • QUICK_REPLY Button:
    • Requires text only
    • Max 3 quick replies per template
  • Button Order: URL → Phone → Quick Reply
  • Only 3 fields required: addSecurityRecommendation, codeExpirationMinutes, copyCodeButton
  • No custom header, body, footer, or buttons
  • Meta auto-generates the template content
  • codeExpirationMinutes range: 1-1440 (1 min to 24 hours)

Response

Success (201 Created)

{
  "success": true,
  "message": "Template created successfully and submitted to Meta for review.",
  "data": {
    "id": 1234,
    "workspace_id": "9ca711b1-14ca-4bd5-9457-751db9c052ac",
    "name": "welcome_template",
    "language": "en",
    "category": "MARKETING",
    "status": "PENDING",
    "provider_id": null,
    "components": {
      "header": { ... },
      "body": { ... },
      "footer": "...",
      "buttons": [ ... ]
    },
    "created_at": "2025-12-03T10:00:00Z",
    "updated_at": "2025-12-03T10:00:00Z"
  }
}

Validation Error (422)

{
  "success": false,
  "message": "Validation failed",
  "errors": {
    "name": ["The name field must only contain lowercase letters and underscores."],
    "body.variables": ["The number of variables must match the placeholders in the text."],
    "header.media.file": ["The file size must not exceed 5120 kilobytes."]
  }
}

Template Status Flow

After creation, templates go through this lifecycle:
PENDING → (Meta Review 5-30 mins) → APPROVED or REJECTED
Use Sync Templates to update the status.

Common Validation Errors

Error MessageCauseSolution
”not_start_or_end_with_var”Text starts/ends with variableRemove variable from start/end
”only_one_variable”Header has more than 1 variableUse max 1 variable in header
”Variable count mismatch”Variables array doesn’t match placeholdersCount {{1}}, {{2}} in text and provide exact number
”File too large”Media exceeds size limitCompress file (Image: 5MB, Video: 10MB, PDF: 30MB)
“Invalid phone number”Missing country codeAdd country code: +1234567890
”Template name exists”Name already usedChoose unique name
”no_more_than_two_consecutive_newlines”Too many blank linesUse max \n\n (2 newlines)

Best Practices

Test Variables

Always test with actual variable values before submission

Keep It Simple

Start with basic templates, add complexity gradually

Follow Meta Guidelines

Avoid promotional language in UTILITY templates

Use Descriptive Names

Use clear names like order_confirmation not template_1

Optimize Media

Compress images/videos before upload

Plan Variables

Map out all dynamic values before creating template

Category Guidelines

Purpose: Promotional messages, offers, announcementsCharacteristics:
  • Can include unsubscribe/block buttons
  • Subject to stricter Meta review
  • Rate limits may apply
Examples:
  • Sales and promotions
  • New product launches
  • Event invitations
  • Newsletter updates

Example cURL Request

curl -X POST \
  https://lancepilot.com/api/v3/workspaces/{workspace}/templates \
  -H 'Authorization: Bearer YOUR_API_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "welcome_template",
    "language": "en",
    "category": "UTILITY",
    "body": {
      "text": "Welcome {{1}}! Your account is now active.",
      "variables": ["John"]
    }
  }'

Need More Examples?Check out TEMPLATE_PAYLOADS.md for 15+ comprehensive template examples covering all use cases.
Meta Review Time: Templates typically take 5-30 minutes for approval. Use the Sync endpoint to check status updates.

Next Steps

After creating a template:
  1. Wait for Review: Meta reviews templates within 5-30 minutes
  2. Sync Status: Use POST /templates/sync
  3. Check Approval: Use GET /templates to verify status
  4. Send Messages: Once approved, use Send Template Message

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Path Parameters

workspace
string<uuid>
required

ID of the workspace.

Body

application/json
name
string
required
Example:

"login_otp_template"

language
string
required
Example:

"en"

category
enum<string>
required
Available options:
MARKETING,
UTILITY,
AUTHENTICATION
body
object
required
header
object

Option 2: Text Header

Maximum string length: 60
buttons
object[]
unsubscribeButton
boolean
blockButton
boolean

Response

Template created successfully