---
title: "Create template"
method: POST
path: "/v1/whatsapp/templates"
tags: ["WhatsApp"]
---

# Create template

`POST /v1/whatsapp/templates`

Create a new message template. Supports two modes:

Custom template: Provide components with your own content. Submitted to Meta for review (can take up to 24h).

Library template: Provide library_template_name instead of components to use a pre-built template
from Meta's template library. Library templates are pre-approved (no review wait). You can optionally
customize parameters and buttons via library_template_body_inputs and library_template_button_inputs.

Browse available library templates at: https://business.facebook.com/wa/manage/message-templates/

## Request body

- object
  - `accountId` string, required — WhatsApp account ID
  - `name` string, required — Template name (lowercase, letters/numbers/underscores, must start with a letter)
  - `category` 'AUTHENTICATION' | 'MARKETING' | 'UTILITY', required — Template category
  - `language` string, required — Template language code (e.g., en_US)
  - `parameter_format` 'POSITIONAL' | 'NAMED' | 'positional' | 'named' — Variable style: POSITIONAL ({{1}}, the default) or NAMED ({{customer_name}}). Named templates provide examples via body_text_named_params / header_text_named_params. Inferred as NAMED when omitted but a named-params example is present.
  - `components` WhatsAppTemplateComponent[] — Template components (header, body, footer, buttons, carousel, limited_time_offer). Required for custom templates, omit when using library_template_name.
    - union
      - WhatsAppHeaderComponent
        - `type` 'header', required
        - `format` 'text' | 'image' | 'video' | 'gif' | 'document' | 'location', required
        - `text` string — Header text (may include {{1}} variable). Used when format is TEXT.
        - `example` object
          - `header_text` string[] — Sample values for header text variables
          - `header_text_named_params` WhatsAppNamedParamExample[] — Sample values for NAMED header variables (templates using {{customer_name}}-style tokens with parameter_format: NAMED).
            - `param_name` string, required — Variable name as it appears in the text, without braces (e.g. customer_name for {{customer_name}}).
            - `example` string, required — Sample value for this variable.
          - `header_handle` string[] — When the header format is a media type (image, video, gif, document), provide a public URL here. Zernio will download and upload it to WhatsApp on your behalf, replacing it with the internal file handle before creating the template.
      - WhatsAppBodyComponent
        - `type` 'body', required
        - `text` string, required — Body text with optional {{n}} variables
        - `add_security_recommendation` boolean — Add security recommendation text (authentication templates only)
        - `example` object
          - `body_text` array[] — Sample values for body variables (array of arrays)
            - string[]
          - `body_text_named_params` WhatsAppNamedParamExample[] — Sample values for NAMED body variables (templates using {{customer_name}}-style tokens with parameter_format: NAMED).
            - `param_name` string, required — Variable name as it appears in the text, without braces (e.g. customer_name for {{customer_name}}).
            - `example` string, required — Sample value for this variable.
      - WhatsAppFooterComponent
        - `type` 'footer', required
        - `text` string — Static footer text
        - `code_expiration_minutes` integer — OTP code expiry in minutes (authentication templates only)
      - WhatsAppButtonsComponent
        - `type` 'buttons', required
        - `buttons` WhatsAppTemplateButton[], required
          - `type` 'quick_reply' | 'url' | 'phone_number' | 'otp' | 'copy_code' | 'flow' | 'mpm' | 'catalog', required
          - `text` string — Visible button label. Required for all types except copy_code (whose label is fixed by WhatsApp) and otp (omit it and WhatsApp supplies its own label, localized to the template language; an English label on a non-English template is rejected).
          - `url` string, uri — Required when type is URL
          - `example` unknown
          - `phone_number` string — Required when type is phone_number
          - `otp_type` 'copy_code' | 'one_tap' | 'zero_tap' — Required when type is otp
          - `autofill_text` string
          - `package_name` string
          - `signature_hash` string
          - `flow_id` string
          - `flow_name` string
          - `flow_json` string
          - `flow_action` string
          - `navigate_screen` string
      - WhatsAppCarouselComponent
        - `type` 'carousel', required
        - `cards` object[], required — 2-10 cards. Meta requires all cards to share the same component structure; a mismatch surfaces as a rejected_reason. MARKETING category only.
          - `components` WhatsAppCarouselCardComponent[], required — Per-card components. Each card carries its own media header + optional body + up to 2 buttons. Footer and nested carousel are not allowed inside cards.
            - union
              - …
      - WhatsAppLimitedTimeOfferComponent
        - `type` 'limited_time_offer', required
        - `limited_time_offer` object, required
          - `text` string, required — Short offer label (<=16 chars). MARKETING only.
          - `has_expiration` boolean — Toggles the countdown timer. The actual coupon code + expiry are bound at SEND time, not here.
  - `library_template_name` string — Name of a pre-built template from Meta's template library (e.g., "appointment_reminder", "auto_pay_reminder_1", "address_update"). When provided, the template is pre-approved by Meta with no review wait. Omit components when using this field.
  - `library_template_body_inputs` object — Optional body customizations for library templates. Available options depend on the template (e.g., add_contact_number, add_learn_more_link, add_security_recommendation, add_track_package_link, code_expiration_minutes).
  - `library_template_button_inputs` object[] — Optional button customizations for library templates. Each item specifies button type and configuration (e.g., URL, phone number, quick reply).
    - `type` 'quick_reply' | 'url' | 'phone_number'
    - `url` object
      - `base_url` string
    - `phone_number` string
  - `message_send_ttl_seconds` integer — Delivery validity window in seconds: a message not delivered within it is dropped. Range depends on category: AUTHENTICATION 30 to 900, UTILITY 30 to 43200 (12h), MARKETING 43200 to 2592000 (30 days); -1 (create only) keeps the 30-day default on AUTHENTICATION and UTILITY. Meta defaults to 600 for AUTHENTICATION and 30 days otherwise. If Meta later recategorises the template, it clears the TTL (read it back to check).

## Response `200`

Template created (pre-approved for library templates, pending review for custom)

- object
  - `success` boolean
  - `template` object
    - `id` string
    - `name` string
    - `status` string — APPROVED for library templates, PENDING for custom
    - `category` string
    - `language` string
    - `message_send_ttl_seconds` integer — Echoed when supplied on the request.

## Other responses

- `400` — Validation error (invalid name format, missing fields, invalid category)
- `401` — Unauthorized
- `404` — WhatsApp account not found

## Changes

- **2026-09-08** `d7a8fa118ef0` — 2 info
  - added the new optional request property `message_send_ttl_seconds`
  - added the optional property `template/message_send_ttl_seconds` to the response with the `200` status

[Change history](https://skmtc.dev/zernio/apis/zernio-api/changes/v1/whatsapp/templates/post.md)

---

[API](https://skmtc.dev/zernio/apis/zernio-api.md) · [All operations](https://skmtc.dev/zernio/apis/zernio-api/llms.txt) · [OpenAPI document](https://skmtc.dev/zernio/apis/zernio-api/revisions/106013ac73b8?raw)
