Skip to content

Templates

View as Markdown

Approved WhatsApp templates: read what each needs, create new ones.

A template is a message WhatsApp approved in advance. It is the only way to start a conversation or to write after the 24-hour window, so order updates, reminders, verification codes and campaigns all use one.

How it works: TemplatesFind what a template needs · Send a template · Create a template · Approval · Delete a template

Find what a template needs#

GET /templates lists them, and each one says what a send must fill in:

JSON
{
  "id": "tpl_27",
  "name": "order_update",
  "language": "ar",
  "status": "approved",
  "variables": { "body": 2, "buttons": [{ "index": 0, "type": "url" }] },
  "send_example": {
    "type": "template",
    "template": {
      "name": "order_update",
      "language": "ar",
      "variables": { "body": ["value 1", "value 2"], "buttons": { "0": { "url_suffix": "value" } } }
    }
  }
}

send_example is a ready body for POST /messages: add to, replace the values, send. Only approved templates can be sent.

Send a template#

JSON
{
  "to": "+966501234567",
  "type": "template",
  "template": {
    "name": "order_update",
    "language": "ar",
    "variables": {
      "body": ["سارة", "#10482"],
      "buttons": { "0": { "url_suffix": "10482" } }
    }
  }
}
VariableFills in
body{{1}}, {{2}}… of the body, in order
header_texta text header's {{1}}
header_media_linkan image, video or document header, as a public https:// link
buttonsby button index: url_suffix (a URL button's {{1}}), coupon_code (copy-code), payload (quick reply)

A wrong number of body values is refused at once with template_variables_mismatch, instead of failing later at WhatsApp.

Create a template#

POST /templates submits a template to WhatsApp. It takes WhatsApp's own components, and every {{n}} needs an example value:

JSON
{
  "name": "order_shipped",
  "language": "ar",
  "category": "utility",
  "components": [
    {
      "type": "BODY",
      "text": "مرحبًا {{1}}، شُحن طلبك رقم {{2}} وسيصلك خلال يومين.",
      "example": { "body_text": [["سارة", "10482"]] }
    },
    {
      "type": "BUTTONS",
      "buttons": [
        { "type": "URL", "text": "تتبّع الشحنة", "url": "https://shop.example.com/track/{{1}}", "example": ["https://shop.example.com/track/10482"] }
      ]
    }
  ]
}
  • Categories. utility is for something the customer is waiting for (an order, an appointment). marketing is for promotions. authentication is for one-time codes, and takes otp instead of components.
  • Media headers. Upload the file with POST /media and put its med_… id in the header's example.header_handle: we hand it to WhatsApp, and later sends use that file unless you pass header_media_link.
  • The checks come first. Name format (lowercase, digits, _), component lengths, button counts, the language list and name uniqueness on the number's WhatsApp account are checked before anything reaches WhatsApp.

Approval#

A new template is pending. WhatsApp usually decides within minutes, sometimes up to 24 hours, and you get template.status_changed:

StatusMeaning
approvedReady to send
rejectedRefused; rejection_reason gives WhatsApp's reason when it gave one
pausedTemporarily stopped by WhatsApp after poor feedback
disabledStopped for good

WhatsApp may also move an approved template to another category (for example utility to marketing), which changes its price. The template's category always shows the current one.

Delete a template#

DELETE /templates/{id} deletes it here and at WhatsApp. It is refused while a scheduled or running campaign uses it. WhatsApp does not let the same name be used again for 30 days.

Endpoints

List templates

gethttps://api.saei.automize.sa/v1/templates
  • Scope: templates:read
  • Works in test mode

Your WhatsApp message templates. Each one says what it needs filled in (variables) and carries a send_example you can paste into POST /v1/messages.

Query parameters

  • limitintegeroptional

    How many objects to return, 1 to 100.

  • cursorstringoptional

    The next_cursor from the previous page.

  • statusstringoptional

    One ofapprovedpendingrejectedpauseddisableddraft

  • categorystringoptional

    One ofmarketingutilityauthentication

  • languagestringoptional

    A language code, e.g. ar or en_US.

  • namestringoptional

    The exact template name.

Response fields200
  • object"list"required
  • dataarray<Template>required
    Child fields (12)
    • idstringrequired
    • object"template"required
    • namestringrequired
    • languagestring | nullrequired
    • categorystring | nulloptional

      One ofmarketingutilityauthenticationnull

    • statusstringrequired

      Only approved templates can be sent.

    • rejection_reasonstring | nulloptional
    • componentsarrayrequired

      HEADER, BODY, FOOTER and BUTTONS, exactly as WhatsApp holds them.

    • variablesobjectrequired

      What a send must fill in: header (the header type that needs a value), body (how many {{n}} placeholders) and buttons (which buttons take a value).

      Child fields (3)
      • headerstringoptional
      • bodyintegeroptional
      • buttonsarray<object>optional
        Child fields (2)
        • indexintegeroptional
        • typestringoptional
    • send_exampleobjectrequired

      A POST /v1/messages body for this template with placeholder values. Add to and your values.

    • created_atstring | nulloptional
    • updated_atstring | nulloptional
  • has_morebooleanrequired
  • next_cursorstring | nullrequired
Errors this can return2
Try it
curl -X GET https://api.saei.automize.sa/v1/templates \
  -H "Authorization: Bearer $API_KEY"
Response

A page of templates.

{
  "object": "list",
  "data": [
    {
      "id": "tpl_27",
      "object": "template",
      "name": "string",
      "language": "string",
      "category": "marketing",
      "status": "string",
      "rejection_reason": "string",
      "components": [],
      "variables": {
        "header": "string",
        "body": 0,
        "buttons": [
          {
            "index": null,
            "type": null
          }
        ]
      },
      "send_example": {},
      "created_at": "2026-10-01T09:30:00Z",
      "updated_at": "2026-10-01T09:30:00Z"
    }
  ],
  "has_more": false,
  "next_cursor": "string"
}

Create a template

posthttps://api.saei.automize.sa/v1/templates
  • Scope: templates:write
  • Live keys only
  • Accepts Idempotency-Key

Submits a new template to WhatsApp for approval. It comes back pending; WhatsApp usually decides within minutes (sometimes up to 24 hours), and you get template.status_changed when it does.

components are WhatsApp's own: HEADER, BODY (required), FOOTER, BUTTONS. Every {{n}} placeholder needs an example value, or WhatsApp rejects the template. The builder's own checks run first (lengths, button counts, the language list, name unique per WhatsApp account), so most mistakes come back at once as parameter_invalid.

For an image, video or document header, upload the file with POST /v1/media and put its med_… id in example.header_handle: we hand it to WhatsApp for you, and the template then sends with that file by default.

Authentication (OTP) templates take otp instead of components, need a plan with OTP verification, and a business verified by Meta.

Headers

  • Idempotency-Keystringoptional

    Any unique string (a UUID is ideal). Retrying with the same key and body returns the first response instead of acting twice. Remembered for 24 hours.

Request body

  • namestringrequired

    Lowercase letters, digits and underscores, e.g. order_shipped.

  • languagestringrequired
  • categorystringrequired

    One ofmarketingutilityauthentication

  • number_idstringoptional

    Which number's WhatsApp account holds the template. Default: your default number.

  • componentsarrayoptional

    WhatsApp template components (HEADER, BODY, FOOTER, BUTTONS), each {{n}} with an example.

  • otpobjectoptional

    For authentication: button_text (e.g. "Copy code"), optional code_expiration_minutes and show_security_recommendation.

Response fields201
  • idstringrequired
  • object"template"required
  • namestringrequired
  • languagestring | nullrequired
  • categorystring | nulloptional

    One ofmarketingutilityauthenticationnull

  • statusstringrequired

    Only approved templates can be sent.

  • rejection_reasonstring | nulloptional
  • componentsarrayrequired

    HEADER, BODY, FOOTER and BUTTONS, exactly as WhatsApp holds them.

  • variablesobjectrequired

    What a send must fill in: header (the header type that needs a value), body (how many {{n}} placeholders) and buttons (which buttons take a value).

    Child fields (3)
    • headerstringoptional
    • bodyintegeroptional
    • buttonsarray<object>optional
      Child fields (2)
      • indexintegeroptional
      • typestringoptional
  • send_exampleobjectrequired

    A POST /v1/messages body for this template with placeholder values. Add to and your values.

  • created_atstring | nulloptional
  • updated_atstring | nulloptional
Errors this can return9
Try it
Example
curl -X POST https://api.saei.automize.sa/v1/templates \
  -H "Authorization: Bearer $API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "order_shipped",
  "language": "ar",
  "category": "utility",
  "components": [
    {
      "type": "BODY",
      "text": "مرحبًا {{1}}، شُحن طلبك رقم {{2}} وسيصلك خلال يومين.",
      "example": {
        "body_text": [
          [
            "سارة",
            "10482"
          ]
        ]
      }
    },
    {
      "type": "BUTTONS",
      "buttons": [
        {
          "type": "URL",
          "text": "تتبّع الشحنة",
          "url": "https://shop.example.com/track/{{1}}",
          "example": [
            "https://shop.example.com/track/10482"
          ]
        }
      ]
    }
  ]
}'
Response

Submitted to WhatsApp; `status` is `pending`.

{
  "id": "tpl_27",
  "object": "template",
  "name": "string",
  "language": "string",
  "category": "marketing",
  "status": "string",
  "rejection_reason": "string",
  "components": [],
  "variables": {
    "header": "string",
    "body": 0,
    "buttons": [
      {
        "index": 0,
        "type": "string"
      }
    ]
  },
  "send_example": {},
  "created_at": "2026-10-01T09:30:00Z",
  "updated_at": "2026-10-01T09:30:00Z"
}

Get a template

gethttps://api.saei.automize.sa/v1/templates/{id}
  • Scope: templates:read
  • Works in test mode

One template, its components as WhatsApp approved them, and for a rejected template WhatsApp's reason when it gave one.

Path parameters

  • idstringrequired

    The object's id.

Response fields200
  • idstringrequired
  • object"template"required
  • namestringrequired
  • languagestring | nullrequired
  • categorystring | nulloptional

    One ofmarketingutilityauthenticationnull

  • statusstringrequired

    Only approved templates can be sent.

  • rejection_reasonstring | nulloptional
  • componentsarrayrequired

    HEADER, BODY, FOOTER and BUTTONS, exactly as WhatsApp holds them.

  • variablesobjectrequired

    What a send must fill in: header (the header type that needs a value), body (how many {{n}} placeholders) and buttons (which buttons take a value).

    Child fields (3)
    • headerstringoptional
    • bodyintegeroptional
    • buttonsarray<object>optional
      Child fields (2)
      • indexintegeroptional
      • typestringoptional
  • send_exampleobjectrequired

    A POST /v1/messages body for this template with placeholder values. Add to and your values.

  • created_atstring | nulloptional
  • updated_atstring | nulloptional
Errors this can return2
Try it
curl -X GET https://api.saei.automize.sa/v1/templates/tpl_27 \
  -H "Authorization: Bearer $API_KEY"
Response

The template.

{
  "id": "tpl_27",
  "object": "template",
  "name": "order_update",
  "language": "ar",
  "category": "utility",
  "status": "approved",
  "rejection_reason": null,
  "components": [
    {
      "type": "BODY",
      "text": "مرحبًا {{1}}، طلبك {{2}} في الطريق."
    },
    {
      "type": "BUTTONS",
      "buttons": [
        {
          "type": "URL",
          "text": "تتبّع الطلب",
          "url": "https://shop.example.com/track/{{1}}"
        }
      ]
    }
  ],
  "variables": {
    "body": 2,
    "buttons": [
      {
        "index": 0,
        "type": "url"
      }
    ]
  },
  "send_example": {
    "type": "template",
    "template": {
      "name": "order_update",
      "language": "ar",
      "variables": {
        "body": [
          "value 1",
          "value 2"
        ],
        "buttons": [
          {
            "url_suffix": "value"
          }
        ]
      }
    }
  },
  "created_at": "2026-08-01T10:00:00Z",
  "updated_at": "2026-08-02T07:30:00Z"
}

Delete a template

deletehttps://api.saei.automize.sa/v1/templates/{id}
  • Scope: templates:write
  • Live keys only

Deletes the template here and at WhatsApp. Refused with resource_in_use while a scheduled or running campaign uses it. WhatsApp does not let the same name be reused for 30 days.

Path parameters

  • idstringrequired

    The object's id.

Response fields200
  • idstringrequired
  • objectstringrequired
  • deletedtruerequired
Errors this can return4
Try it
curl -X DELETE https://api.saei.automize.sa/v1/templates/tpl_27 \
  -H "Authorization: Bearer $API_KEY"
Response

Deleted.

{
  "id": "tpl_27",
  "object": "template",
  "deleted": true
}