External APItemplatesCreate Template

Create Template

Overview

This API creates a WhatsApp message template through WappCloud’s platform by submitting it directly to Meta for review.

Templates with media headers (Image, Document, Video) require uploading the file first via the Upload Media endpoint to obtain the h handle and s3Url.


Endpoint

POST https://client-api.wappcloud.com/api/v1/external/templates

Headers

HeaderDescription
x-api-key(Required) Your API Key for authentication
Authorization(Required) Bearer Token
Content-Typeapplication/json

Common Fields

FieldTypeRequiredDescription
namestringYesLowercase letters, numbers, and underscores only. Max 512 chars
categorystringYesMARKETING, UTILITY, or AUTHENTICATION
languagestringYesLanguage code e.g. en_US, hi, ta, ar
componentsarrayYesArray of component objects (HEADER, BODY, FOOTER, BUTTONS, CAROUSEL)
s3UrlstringNoRequired only for media header templates (from Upload Media)
cardS3Urlsarray of stringNoRequired only for carousel templates — one S3 URL per card, in the same order as cards (from Upload Media)
allow_category_changebooleanNoIf true, Meta may reassign the category automatically

Setting Up in Postman

  1. Select the Body tab
  2. Choose raw
  3. From the dropdown select JSON
  4. Paste the request body

Request Payloads


1. Static — Text Body Only

The simplest template. No header, no footer, no buttons.

{
  "name": "static_text_only",
  "category": "UTILITY",
  "language": "en_US",
  "components": [
    {
      "type": "BODY",
      "text": "Your order has been confirmed. Thank you for shopping with us."
    }
  ]
}

{
  "name": "static_text_header_footer",
  "category": "MARKETING",
  "language": "en_US",
  "components": [
    {
      "type": "HEADER",
      "format": "TEXT",
      "text": "Welcome to WappCloud!"
    },
    {
      "type": "BODY",
      "text": "We are excited to have you on board. Explore all the features available to you."
    },
    {
      "type": "FOOTER",
      "text": "Reply STOP to unsubscribe"
    }
  ]
}

Step 1: Upload image via Upload Media → get h and s3Url. Step 2: Use those values below.

{
  "name": "static_image_header",
  "category": "MARKETING",
  "language": "en_US",
  "s3Url": "<s3Url from upload response>",
  "components": [
    {
      "type": "HEADER",
      "format": "IMAGE",
      "example": {
        "header_handle": ["<h from upload response>"]
      }
    },
    {
      "type": "BODY",
      "text": "Check out our latest collection. Limited time offer!"
    },
    {
      "type": "FOOTER",
      "text": "Terms and conditions apply"
    }
  ]
}

4. Static — Document Header + Body

Upload a PDF first via Upload Media.

{
  "name": "static_document_header",
  "category": "UTILITY",
  "language": "en_US",
  "s3Url": "<s3Url from upload response>",
  "components": [
    {
      "type": "HEADER",
      "format": "DOCUMENT",
      "example": {
        "header_handle": ["<h from upload response>"]
      }
    },
    {
      "type": "BODY",
      "text": "Please find your invoice attached. Contact us for any queries."
    },
    {
      "type": "FOOTER",
      "text": "WappCloud Billing"
    }
  ]
}

5. Static — Video Header + Body

Upload an MP4 first via Upload Media.

{
  "name": "static_video_header",
  "category": "MARKETING",
  "language": "en_US",
  "s3Url": "<s3Url from upload response>",
  "components": [
    {
      "type": "HEADER",
      "format": "VIDEO",
      "example": {
        "header_handle": ["<h from upload response>"]
      }
    },
    {
      "type": "BODY",
      "text": "Watch our product demo. We think you will love it!"
    },
    {
      "type": "FOOTER",
      "text": "WappCloud Team"
    }
  ]
}

6. Dynamic — Body Variables Only

Use {{1}}, {{2}}, {{3}} as placeholders in the body. Provide example values in body_text (one array per placeholder, in order).

{
  "name": "dynamic_body_variables",
  "category": "UTILITY",
  "language": "en_US",
  "components": [
    {
      "type": "BODY",
      "text": "Hi {{1}}, your order #{{2}} has been shipped. Expected delivery: {{3}}.",
      "example": {
        "body_text": [["John", "ORD-9821", "Dec 25, 2024"]]
      }
    }
  ]
}

7. Dynamic — Text Header Variable + Body Variables

The header text can also contain a variable {{1}}.

{
  "name": "dynamic_text_header_body",
  "category": "MARKETING",
  "language": "en_US",
  "components": [
    {
      "type": "HEADER",
      "format": "TEXT",
      "text": "Hello {{1}}!",
      "example": {
        "header_text": ["Sarah"]
      }
    },
    {
      "type": "BODY",
      "text": "Your exclusive {{1}}% discount is valid until {{2}}. Use code {{3}} at checkout.",
      "example": {
        "body_text": [["20", "Dec 31, 2024", "SAVE20"]]
      }
    },
    {
      "type": "FOOTER",
      "text": "WappCloud Rewards"
    }
  ]
}

8. Dynamic — Image Header + Body Variables

{
  "name": "dynamic_image_header_body",
  "category": "MARKETING",
  "language": "en_US",
  "s3Url": "<s3Url from upload response>",
  "components": [
    {
      "type": "HEADER",
      "format": "IMAGE",
      "example": {
        "header_handle": ["<h from upload response>"]
      }
    },
    {
      "type": "BODY",
      "text": "Hi {{1}}, your appointment is confirmed for {{2}} at {{3}}.",
      "example": {
        "body_text": [["Rahul", "Monday, Dec 23", "10:00 AM"]]
      }
    },
    {
      "type": "FOOTER",
      "text": "Reply NO to cancel"
    }
  ]
}

9. Dynamic — Document Header + Body Variables

{
  "name": "dynamic_document_header_body",
  "category": "UTILITY",
  "language": "en_US",
  "s3Url": "<s3Url from upload response>",
  "components": [
    {
      "type": "HEADER",
      "format": "DOCUMENT",
      "example": {
        "header_handle": ["<h from upload response>"]
      }
    },
    {
      "type": "BODY",
      "text": "Hi {{1}}, your invoice #{{2}} for ₹{{3}} is ready for download.",
      "example": {
        "body_text": [["Priya", "INV-4521", "2,500"]]
      }
    },
    {
      "type": "FOOTER",
      "text": "WappCloud Billing"
    }
  ]
}

10. Dynamic — Video Header + Body Variables

{
  "name": "dynamic_video_header_body",
  "category": "MARKETING",
  "language": "en_US",
  "s3Url": "<s3Url from upload response>",
  "components": [
    {
      "type": "HEADER",
      "format": "VIDEO",
      "example": {
        "header_handle": ["<h from upload response>"]
      }
    },
    {
      "type": "BODY",
      "text": "Hi {{1}}, here is your personalised product demo for {{2}}.",
      "example": {
        "body_text": [["Arun", "WappCloud Pro"]]
      }
    },
    {
      "type": "FOOTER",
      "text": "WappCloud Team"
    }
  ]
}

11. Static — Quick Reply Buttons

Up to 3 quick reply buttons. No variables needed.

{
  "name": "quick_reply_static",
  "category": "MARKETING",
  "language": "en_US",
  "components": [
    {
      "type": "BODY",
      "text": "Are you interested in our new product launch this weekend?"
    },
    {
      "type": "FOOTER",
      "text": "WappCloud"
    },
    {
      "type": "BUTTONS",
      "buttons": [
        { "type": "QUICK_REPLY", "text": "Yes, tell me more!" },
        { "type": "QUICK_REPLY", "text": "No, thanks" },
        { "type": "QUICK_REPLY", "text": "Remind me later" }
      ]
    }
  ]
}

12. Static — Call to Action Buttons (URL + Phone)

{
  "name": "cta_url_and_phone",
  "category": "UTILITY",
  "language": "en_US",
  "components": [
    {
      "type": "BODY",
      "text": "Your payment is due. Pay now online or call our support team for assistance."
    },
    {
      "type": "FOOTER",
      "text": "WappCloud Billing"
    },
    {
      "type": "BUTTONS",
      "buttons": [
        {
          "type": "URL",
          "text": "Pay Now",
          "url": "https://billing.wappcloud.com/pay",
          "example": ["https://billing.wappcloud.com/pay"]
        },
        {
          "type": "PHONE_NUMBER",
          "text": "Call Support",
          "phone_number": "+9199xxxxxx"
        }
      ]
    }
  ]
}

13. Dynamic — URL Button with Variable

The URL can contain a variable {{1}} that is replaced at send time (e.g., a unique tracking ID per recipient).

{
  "name": "dynamic_url_button",
  "category": "UTILITY",
  "language": "en_US",
  "components": [
    {
      "type": "BODY",
      "text": "Hi {{1}}, your shipment is on its way. Track it in real time.",
      "example": {
        "body_text": [["Priya"]]
      }
    },
    {
      "type": "BUTTONS",
      "buttons": [
        {
          "type": "URL",
          "text": "Track Order",
          "url": "https://track.wappcloud.com/{{1}}",
          "example": ["https://track.wappcloud.com/ORD-9821"]
        }
      ]
    }
  ]
}

14. Dynamic — Quick Reply + Body Variables

{
  "name": "dynamic_body_quick_reply",
  "category": "MARKETING",
  "language": "en_US",
  "components": [
    {
      "type": "BODY",
      "text": "Hi {{1}}, your exclusive offer of {{2}}% off expires on {{3}}. Would you like to claim it?",
      "example": {
        "body_text": [["Arun", "30", "Dec 31, 2024"]]
      }
    },
    {
      "type": "FOOTER",
      "text": "WappCloud Deals"
    },
    {
      "type": "BUTTONS",
      "buttons": [
        { "type": "QUICK_REPLY", "text": "Claim Offer" },
        { "type": "QUICK_REPLY", "text": "Not Interested" }
      ]
    }
  ]
}

15. Full Template — All Sections Dynamic

Image header + body variables + footer + mixed buttons (URL with variable + phone + quick reply).

{
  "name": "full_dynamic_all_sections",
  "category": "MARKETING",
  "language": "en_US",
  "s3Url": "<s3Url from upload response>",
  "components": [
    {
      "type": "HEADER",
      "format": "IMAGE",
      "example": {
        "header_handle": ["<h from upload response>"]
      }
    },
    {
      "type": "BODY",
      "text": "Hi {{1}}, your {{2}} is ready for pickup at {{3}}. Show this message at the counter.",
      "example": {
        "body_text": [["Arun", "order", "MG Road Store"]]
      }
    },
    {
      "type": "FOOTER",
      "text": "WappCloud | Valid today only"
    },
    {
      "type": "BUTTONS",
      "buttons": [
        {
          "type": "URL",
          "text": "View Order",
          "url": "https://wappcloud.com/orders/{{1}}",
          "example": ["https://wappcloud.com/orders/ORD-9821"]
        },
        {
          "type": "PHONE_NUMBER",
          "text": "Call Store",
          "phone_number": "+9199xxxxxx"
        },
        {
          "type": "QUICK_REPLY",
          "text": "Confirm Pickup"
        }
      ]
    }
  ]
}

16. Authentication — OTP Template

Used for sending one-time passwords. Category must be AUTHENTICATION.

{
  "name": "otp_verification_code",
  "category": "AUTHENTICATION",
  "language": "en_US",
  "components": [
    {
      "type": "BODY",
      "text": "{{1}} is your verification code. For your security, do not share this code.",
      "add_security_recommendation": true,
      "example": {
        "body_text": [["123456"]]
      }
    },
    {
      "type": "FOOTER",
      "text": "This code expires in 10 minutes.",
      "code_expiration_minutes": 10
    },
    {
      "type": "BUTTONS",
      "buttons": [
        {
          "type": "OTP",
          "otp_type": "COPY_CODE",
          "text": "Copy Code"
        }
      ]
    }
  ]
}

A carousel template shows several swipeable cards in one message, each with its own image and buttons — useful for showcasing a small product catalog. Upload each card’s image first via Upload Media to get its h handle and S3 URL.

The top-level components array has one CAROUSEL entry holding all the cards. cardS3Urls lists each card’s S3 URL, in the same order as cards.

{
  "name": "product_carousel_v1",
  "category": "MARKETING",
  "language": "en_US",
  "cardS3Urls": [
    "<s3Url for card 1 from upload response>",
    "<s3Url for card 2 from upload response>"
  ],
  "components": [
    {
      "type": "BODY",
      "text": "Check out this week's top picks!"
    },
    {
      "type": "CAROUSEL",
      "cards": [
        {
          "components": [
            {
              "type": "HEADER",
              "format": "IMAGE",
              "example": {
                "header_handle": ["<h for card 1 from upload response>"]
              }
            },
            {
              "type": "BUTTONS",
              "buttons": [
                { "type": "QUICK_REPLY", "text": "View Product" }
              ]
            }
          ]
        },
        {
          "components": [
            {
              "type": "HEADER",
              "format": "IMAGE",
              "example": {
                "header_handle": ["<h for card 2 from upload response>"]
              }
            },
            {
              "type": "BUTTONS",
              "buttons": [
                { "type": "QUICK_REPLY", "text": "View Product" }
              ]
            }
          ]
        }
      ]
    }
  ]
}
  • Each card can carry its own HEADER (image) and BUTTONS components, similar to a small template of its own.
  • A carousel template needs at least one card, and every card should follow the same layout (same component types) since Meta reviews them as one design.
  • When sending a message using a carousel template, you provide one entry per card in the carousel array — see Carousel Template in the Send Messages guide.

Response (Success)

{
  "success": true,
  "code": 200,
  "message": "Template created successfully",
  "data": {
    "id": "1234567890123456",
    "status": "PENDING",
    "category": "MARKETING"
  }
}
FieldDescription
idMeta’s template ID
statusInitial status — always PENDING until Meta reviews and approves it
categoryThe category assigned (Meta may change this if allow_category_change is true)

Error Responses

400 Bad Request

Returned when the payload is invalid (e.g. missing required field, invalid category, invalid language code).

{
  "success": false,
  "code": 400,
  "message": "Invalid request body"
}

401 Unauthorized

{
  "error": "Missing authToken or x-api-key"
}

Notes

  • Template name rules: lowercase letters, numbers, and underscores only (a-z, 0-9, _). No spaces or uppercase.
  • Variable order: must be sequential starting at {{1}} — e.g. {{1}}, {{2}}, {{3}}. Skipping numbers is not allowed.
  • Media templates: always call Upload Media first to get h and s3Url.
  • example values: required by Meta for all components that contain variables or media. They are sample values shown during template review — they are not sent to the end user.
  • Status after creation: templates are always PENDING initially. Use List Templates to check when a template moves to APPROVED or REJECTED.
  • Language codes: use valid WhatsApp language codes — e.g. en_US (English), hi (Hindi), ta (Tamil), ar (Arabic). See Meta’s documentation for the full list.
  • Carousel templates: supported via a CAROUSEL component with one or more cards — see example 17 above. Each card’s media is uploaded the same way as any other template media, via Upload Media.
  • Video headers: an .mp4 file extension is not enough on its own — see Video File Requirements if a video header doesn’t play correctly after the template is approved.