Template Definition

A template definition is the JSON document that describes a template's content. It is the required definition field of the Create Template (POST /v3/templates) and Update Template (PUT /v3/templates/{id}) requests. The dashboard template builder displays the same JSON via its View JSON action.

Top-level request fields use snake_case (submit_for_review); field names inside definition use camelCase (multiChannel, variableType).

Create template request

FieldTypeRequiredDescription
categorystringNoMARKETING, UTILITY, or AUTHENTICATION. Auto-detected from the template content when omitted
languagestringNoLanguage code (for example, en_US). Auto-detected from the template content when omitted
definitionobjectYesThe definition object
creation_sourcestringNoSource label for the template. Default: from-api
submit_for_reviewbooleanNotrue submits the template for review immediately after creation. Default: false, which saves the template with status DRAFT

Definition object

FieldTypeRequiredDescription
headerobjectNoHeader object
bodyobjectYesBody object
footerobjectNoFooter object
buttonsarrayNoArray of button objects
definitionVersionstringNoVersion of the template definition format
authenticationConfigobjectNoAuthentication configuration, used only by AUTHENTICATION templates

Channel support

ComponentSMSWhatsAppRCS
HeaderNot supportedNative headerPrepended to message text
BodySupportedSupportedSupported
FooterNot supportedNative footerAppended to message text
ButtonsNot supportedInteractive buttonsFirst four shown as suggestion chips

Header object

FieldTypeRequiredDescription
typestringNoHeader type: text, image, video, or document
templatestringYesHeader text with optional variable placeholders. Maximum 60 characters
variablesarrayNoVariable objects used in the header. Maximum 1

Text headers must not contain newlines, emojis, or formatting markup (*, _, ~). AUTHENTICATION templates do not use headers; Sent excludes any header from them automatically.

Body object

The body carries channel-specific content. multiChannel applies to every channel unless a channel-specific override is present.

FieldTypeRequiredDescription
multiChannelobjectNoBody content used for all channels without an override
smsobjectNoBody content that overrides multiChannel for SMS
whatsappobjectNoBody content that overrides multiChannel for WhatsApp
rcsobjectNoBody content that overrides multiChannel for RCS

Body content object

FieldTypeRequiredDescription
typestringNoBody type: body
templatestringYesBody text with variable placeholders. Maximum 1024 characters
variablesarrayNoVariable objects used in the body. IDs must be unique within the body
FieldTypeRequiredDescription
typestringNoFooter type: text
templatestringYesFooter text. Maximum 60 characters
variablesarrayNoMust be empty; footers cannot contain variables

Footers must not contain variables, newlines, emojis, or formatting markup (*, _, ~).

Buttons array

A template holds a maximum of 10 buttons. Button IDs must be unique. Per-type limits: maximum 1 COPY_CODE, 1 PHONE_NUMBER, 2 URL, and 10 QUICK_REPLY buttons.

FieldTypeRequiredDescription
idnumberNoButton identifier (1-based index). Must be unique within the template
typestringYesQUICK_REPLY, URL, VOICE_CALL, PHONE_NUMBER, or COPY_CODE
propsobjectYesType-specific button properties

Button props object

FieldTypeApplies toDescription
textstringAll typesButton label. Maximum 25 characters
quickReplyTypestringQUICK_REPLYcustom or pre-configured
urlTypestringURLstatic or dynamic
urlstringURLDestination URL. Maximum 2000 characters
variablesarrayURL (dynamic)Exactly 1 variable object; its placeholder must appear at the end of url
activeFornumberVOICE_CALLInteger greater than 0
countryCodestringPHONE_NUMBERCountry code (for example, US)
phoneNumberstringPHONE_NUMBERPhone number in international format
offerCodestringCOPY_CODECode copied to the clipboard on tap
otpTypestringAUTHENTICATION OTP buttonsCOPY_CODE or ONE_TAP

Variable object

Variables use a numbered placeholder syntax in template text: {{0:variable}} for text variables and {{4:link}} for links, where the number is the variable's id.

FieldTypeRequiredDescription
idnumberNoSequential ID starting from 0, unique within its section
namestringYesReadable identifier for the variable (for example, orderNumber)
typestringYesvariable, link, or media
propsobjectYesVariable properties

Variable props object

FieldTypeApplies toDescription
variableTypestringvariableRequired. text, link, image, or file
samplestringvariableRequired. Example value shown in previews and used during review
regexstringvariableOptional validation pattern for the variable value
urlstringlink, mediaRequired. Full HTTP or HTTPS URL
shortUrlstringlinkOptional shortened URL
altstringlink, mediaAlternative text
mediaTypestringmediaRequired. image, video, or document

Authentication configuration

AUTHENTICATION templates accept an authenticationConfig object:

FieldTypeDescription
addSecurityRecommendationbooleanAdds the text "For your security, do not share this code."
codeExpirationMinutesnumber1–90. When set, adds the footer "This code expires in X minutes."

An AUTHENTICATION body must declare exactly one text variable (the code) and must not contain links or emojis.

Content rules and limits

RuleLimit
Body length1024 characters per channel body
Header and footer length60 characters each
Header variables1
Buttons per template10
Button label length25 characters
Button URL length2000 characters
Variables in a dynamic URL buttonExactly 1, at the end of the URL
Emojis in a MARKETING body10

Length limits are validated at save time against the stored text, with {{...}} placeholders unsubstituted. Counting is encoding-blind: each UTF-16 code unit counts as one character (the behavior of .NET's string.Length and JavaScript's String.prototype.length), so characters in the Basic Multilingual Plane count as 1 and most emoji count as 2. There is no post-substitution validation; a body within the limit can render into a longer message once variables expand. For how rendered length maps to SMS segments, see SMS Encoding & Message Length.

Body text must additionally satisfy these rules:

  • Must not start or end with a newline, and must not contain more than two consecutive line breaks or more than four consecutive spaces.
  • Must contain at least one letter before the first variable and after the last variable; variables cannot be adjacent without text between them.
  • Word count must be at least (2 × variable count) + 1.

Template statuses

StatusMeaning
DRAFTCreated but not submitted. Editable and testable; cannot be sent on any channel
PENDINGSubmitted for review; awaiting a decision
APPROVEDApproved; available for sending
REJECTEDDeclined by the reviewer. A rejected template must be revised and resubmitted before it can send
PAUSEDPaused by Meta; sends against the template are blocked until it is reinstated

Review routing depends on your account:

  • With a connected WhatsApp Business Account, Meta reviews the template. A Meta APPROVED or PENDING verdict applies to every channel (SMS, WhatsApp, and RCS); a REJECTED verdict applies to the WhatsApp channel only.
  • Without a connected WhatsApp Business Account, Sent's compliance team reviews the template, and each channel is approved or rejected individually.

Approval is tracked per channel. A message sends on a channel only when the template is approved for that channel; sends against unapproved templates return status BLOCKED. Status changes are delivered as templates webhook events carrying the template ID, channel, status, and reason.

Example

A complete POST /v3/templates request body with a header, a multi-channel body using text variables and a dynamic link, a footer, and two buttons:

{
  "category": "UTILITY",
  "language": "en_US",
  "submit_for_review": false,
  "definition": {
    "header": {
      "type": "text",
      "template": "Order {{0:variable}}: Delivery Update",
      "variables": [
        {
          "id": 0,
          "name": "orderNumber",
          "type": "variable",
          "props": {
            "variableType": "text",
            "sample": "12345"
          }
        }
      ]
    },
    "body": {
      "multiChannel": {
        "type": "body",
        "template": "Hi {{0:variable}},\nYour Acme order {{1:variable}} has been shipped and is expected to arrive {{2:variable}} between {{3:variable}}.\nYou can track your package or update your delivery preferences at {{4:link}} before the driver arrives.",
        "variables": [
          {
            "id": 0,
            "name": "customerName",
            "type": "variable",
            "props": {
              "variableType": "text",
              "sample": "Lucas"
            }
          },
          {
            "id": 1,
            "name": "orderNumber",
            "type": "variable",
            "props": {
              "variableType": "text",
              "sample": "#12345"
            }
          },
          {
            "id": 2,
            "name": "arrivalDate",
            "type": "variable",
            "props": {
              "variableType": "text",
              "sample": "tomorrow (Oct 11)"
            }
          },
          {
            "id": 3,
            "name": "arrivalTime",
            "type": "variable",
            "props": {
              "variableType": "text",
              "sample": "2 PM – 4 PM"
            }
          },
          {
            "id": 4,
            "name": "orderLink",
            "type": "link",
            "props": {
              "url": "https://example.com",
              "shortUrl": "",
              "alt": "Tracking Page"
            }
          }
        ]
      }
    },
    "footer": {
      "type": "text",
      "template": "Thank you for shopping with Acme.",
      "variables": []
    },
    "buttons": [
      {
        "id": 1,
        "type": "URL",
        "props": {
          "text": "Track your order",
          "urlType": "static",
          "url": "https://www.example.com/track"
        }
      },
      {
        "id": 2,
        "type": "PHONE_NUMBER",
        "props": {
          "text": "Acme customer support",
          "countryCode": "US",
          "phoneNumber": "+112345678"
        }
      }
    ]
  }
}

The endpoint responds with the standard response envelope; the created template's fields are documented on the Create Template endpoint page.

On this page