Creating WhatsApp Message templates

Step-by-step process of creating a Whatsapp Message Template using the Touchpoints API.

Creating WhatsApp Message Templates

To create a WhatsApp approved message template via the API, follow these steps:

  1. Create a Project -- a project houses the messaging template.

  2. Retrieve a Channel Group -- templates are linked to a WABA (WhatsApp Business Account) via a channel group.

  3. Preview the Template (optional) -- validate content and see a rendered preview before creating.

  4. Create a Channel Template -- define the template content, variables, and deployments.

  5. Activate the Template -- submit the template to Meta for approval.

  6. Check the Template Status -- monitor approval status, quality rating, and platform-specific details.

  7. Update a Template -- modify draft templates in-place or create new versions of active/inactive templates.

Once the template is approved by Meta, it can be used for sending messages by following the Sending WhatsApp Messagesarrow-up-right guide.

circle-info

Before starting this guide, make sure you have API Accessarrow-up-right and are using the necessary Access Policies and Roles on your Access Key.

circle-info

platformContent defines the template structure using "blocks." The structure varies depending on the template type. See the WhatsApp Template Blocks Reference for all supported block types and examples.


1 -- Create a Project

Create a Message Template project where the WhatsApp template will be added.

Create project

post
Authorizations
HTTPRequired

Uses the Authorization header: 'AccessKey ' followed by your access key token (e.g., 'Authorization: AccessKey AbCdEfGhIjKlMnOpQrStUvWxYzAbCdEfGhIj')

Path parameters
workspaceIdstringRequired
Body
namestringOptional
descriptionstringOptional
typestring · enumRequired

enum for all the different project types Touchpoints API supports.

Possible values:
scopenumber · enumOptional

dictionary:

  • 0 DEFAULT: This should indicate that the project is of our current scope (can be used across all BirdCRM services).
  • 1 SAVED_TEMPLATE: This should indicate that the project is a saved template, meaning that it came from extending one of BirdCRM library templates. They can be used for creating other Projects, such as inline campaigns and flows content.
  • 2 INLINE_MESSAGE: This should indicate that the project is an inline message, meaning that it was created from a campaign or flow using a library template or a saved template. They are linked to an specific instance of other BirdCRM services (Campaigns, Flows, etc.).
  • 3 (PLATFORM_REVIEWED_TEMPLATE): This should indicate that the project is a platform reviewed template, meaning the template must go through a external platform review.
Possible values:
tagsstring[] · nullableOptional

Tags for this project

directoryIdstring · uuid · nullableOptional
Responses
post
/workspaces/{workspaceId}/projects

Example request:

Field
Description

type

Must be channelTemplate for message templates

scope

Must be 3 (platform-reviewed template) -- Meta requires templates to be submitted for review

name

A unique project name

suites

The suite where this template will be used (e.g. marketing, service)

Example response:

Save the project id -- you will need it for the next steps.


2 -- Retrieve a Channel Group

Use the channel groups endpoint to find the channel group ID associated with your WABA. Templates are linked to a specific WABA through a channel group.

Get enriched Channel groups for ChannelTemplate

get
Authorizations
HTTPRequired

Uses the Authorization header: 'AccessKey ' followed by your access key token (e.g., 'Authorization: AccessKey AbCdEfGhIjKlMnOpQrStUvWxYzAbCdEfGhIj')

Path parameters
workspaceIdstringRequired
Responses
chevron-right
200

OK

application/json
get
/workspaces/{workspaceId}/projects/channel-templates/channel-groups

Example response:

Field
Description

id

The channel group ID -- required for creating a template. Has a one-to-one relationship with your WABA.

platformGroupId

Your WABA ID

platformGroupName

Your WABA name

channelIds

List of WhatsApp channels associated with this WABA

Save the channel group id -- you will need it when creating the template in step 4.


3 -- Preview the Template (Optional)

Before creating a template, you can use the preview endpoint to validate the content and resolve variables. This catches structural or validation errors early, before the template is submitted to Meta.

The preview endpoint returns JSON (not HTML). The response format depends on the template type:

  • Standard templates (text, image, file/video): Returns type: "body" with the resolved Channels API message body structure -- the WhatsApp template payload with variables substituted.

  • Complex WhatsApp-specific templates (carousel, catalog, multi-product, coupon, flow, etc.): Returns type: "blocks" with the blocks returned back, variables substituted, and styles applied.

In both cases, the response includes a validationErrors object that flags any issues.

Create ChannelTemplate Preview

post
Authorizations
HTTPRequired

Uses the Authorization header: 'AccessKey ' followed by your access key token (e.g., 'Authorization: AccessKey AbCdEfGhIjKlMnOpQrStUvWxYzAbCdEfGhIj')

Path parameters
workspaceIdstringRequired
Body
platformstring · min: 1Optional
shortLinksobject · nullableOptional
contactIdstring · nullableOptional
localestring · locale-bcp47 · nullableOptional
Responses
chevron-right
200

OK

application/json
typestring · enumOptionalPossible values:
post
/workspaces/{workspaceId}/projects/channel-templates/create-preview

Example request:

Field
Type
Description

platform

string

Target platform -- use whatsapp

locale

string

BCP 47 locale code (e.g. en, pt_BR)

blocks

array

The template blocks to preview (same structure as in the create request)

variables

object

Sample variable values to substitute in the preview

contactId

string

(Optional) A contact ID to resolve contact-level variables

Example response -- standard text template (type: body):

Example response -- complex template (type: blocks):

For WhatsApp-specific templates like carousel, catalog, multi-product, coupon, flow, and limited time offer, the API returns the blocks with variables resolved:

Example response -- validation errors:

If the template content has issues, the validationErrors object contains field-level errors:

circle-info

The preview endpoint does not create or persist anything -- it only validates and resolves variables. You can call it as many times as needed while iterating on your template content.


4 -- Create a Channel Template

Create the actual WhatsApp template with its content, variables, and deployment settings.

circle-exclamation

Create channeltemplate

post
Authorizations
HTTPRequired

Uses the Authorization header: 'AccessKey ' followed by your access key token (e.g., 'Authorization: AccessKey AbCdEfGhIjKlMnOpQrStUvWxYzAbCdEfGhIj')

Path parameters
workspaceIdstringRequired
projectIdstringRequired
Query parameters
metricsbooleanOptional

Include metrics in the response

Default: false
Body
descriptionstringOptional
defaultLocaleall ofOptional
string · enumOptionalExample: enPossible values:
shortLinksobject · nullableOptional
Other propertiesanyOptional
Responses
post
/workspaces/{workspaceId}/projects/{projectId}/channel-templates

Example request (text template):

Deployment fields

Field
Description

whatsappTemplateName

Template name registered with Meta. Must be lowercase with underscores only.

whatsappCategory

Template category: MARKETING or UTILITY. The AUTHENTICATION category can only be used with Authentication Template Blocks.

whatsappAllowCategoryChange

Always set to "true". Meta enforces category changes regardless of this setting. Still required by the API but may be deprecated in a future release.

Other key fields

Field
Description

defaultLocale

Fallback locale if the specified content locale is not supported

platformContent

Platform-specific content. See the WhatsApp Template Blocks Reference for all supported block types (text, image, file/video, carousel, catalog, coupon, flow, multi-product, limited time offer, authentication).

platformContent.channelGroupIds

Channel group ID from step 2, linking this template to your WABA

variables

Variables used in the template body (e.g. {{firstname}}). Each must include example values for Meta's review.

supportedPlatforms

Set to ["whatsapp"] for WhatsApp-only templates

Example response:

Field
Description

id

The channel template ID -- required for activation and status checks

projectId

The project ID -- required when sending messages via the Channels API

status

draft indicates the template has been created and the next step is to preview or activate it


5 -- Activate the Template

Activating a template submits it to Meta for approval. Meta reviews the template to ensure it complies with their guidelines, assessing structure, content, language, and intended use case.

Activate ChannelTemplate

put
Authorizations
HTTPRequired

Uses the Authorization header: 'AccessKey ' followed by your access key token (e.g., 'Authorization: AccessKey AbCdEfGhIjKlMnOpQrStUvWxYzAbCdEfGhIj')

Path parameters
workspaceIdstringRequired
projectIdstringRequired
channelTemplateIdstringRequired
Responses
chevron-right
200

Activated

No content

put
/workspaces/{workspaceId}/projects/{projectId}/channel-templates/{channelTemplateId}/activate

No content

No request body is needed. If successful, you receive a 200 OK response and the template status changes to pending:

If approval is successful, the template status changes to active and is ready for sending messagesarrow-up-right.

Deactivating a template

To deactivate a template that has already been activated:

Deactivate ChannelTemplate

put
Authorizations
HTTPRequired

Uses the Authorization header: 'AccessKey ' followed by your access key token (e.g., 'Authorization: AccessKey AbCdEfGhIjKlMnOpQrStUvWxYzAbCdEfGhIj')

Path parameters
workspaceIdstringRequired
projectIdstringRequired
channelTemplateIdstringRequired
Responses
chevron-right
200

Deactivated

No content

put
/workspaces/{workspaceId}/projects/{projectId}/channel-templates/{channelTemplateId}/deactivate

No content


6 -- Check the Template Status

After activation, use the Get ChannelTemplate endpoint to check the current approval status, quality rating, and any rejection reasons.

Get ChannelTemplate

get
Authorizations
HTTPRequired

Uses the Authorization header: 'AccessKey ' followed by your access key token (e.g., 'Authorization: AccessKey AbCdEfGhIjKlMnOpQrStUvWxYzAbCdEfGhIj')

Path parameters
workspaceIdstringRequired
projectIdstringRequired
channelTemplateIdstringRequired
Responses
chevron-right
200

OK

application/json
idstring · uuidRequired
projectIdstring · uuidRequired
statusstring · enumOptionalPossible values:
descriptionstringOptional
defaultLocalestring · enumOptionalExample: enPossible values:
createdAtstring · date-timeRequired
updatedAtstring · date-timeOptional
isCloneablebooleanOptional
editorIdstring · uuidOptional
editorTypestringOptional
publisherIdstring · uuidOptional

The ID of the user that last published this ChannelTemplate.

publisherTypestring · stringOptional
shortLinksobject · nullableOptional
clonedFromstring · uuid · nullableOptional

The ID of the template that this template was cloned from. This field is only present if this template was cloned from another template.

metricsobjectOptional

Metrics for this template.

get
/workspaces/{workspaceId}/projects/{projectId}/channel-templates/{channelTemplateId}

Example response (approved template):

Template-level status

The top-level status reflects the overall template state across all WABAs and locales.

Status
Can send?
Description

draft

No

Template created but not yet submitted to Meta

pending

No

Template submitted to Meta for review

active

Yes

Approved by Meta on at least one WABA/locale

inactive

No

Rejected, paused, or disabled on all WABAs/locales

pendingReview

No

Pending internal Bird approval (when approval flows are configured)

circle-exclamation

Platform-level status (platformInfo)

The platformInfo object contains per-WABA/locale status. Each key follows the format whatsapp:{wabaId}:{locale}.

Field
Description

platformInfo.status

Simplified approval status: active, inactive, or pending

platformInfo.category

Category assigned by Meta. May differ from your requested category if Meta re-categorized the template.

platformInfo.qualityRating

Quality rating from Meta: GREEN (healthy), YELLOW (declining), RED (at risk of pausing), or UNKNOWN (not yet rated)

Approval details (platformContent.approvals)

Each approval in platformContent[].approvals[] provides detailed status for a specific WABA.

Field
Description

status

Approval status: pending, approved, rejected, blocked, or deleted

platformStatus

Detailed Meta status: whatsapp_approved, whatsapp_flagged, whatsapp_rejected, whatsapp_paused, whatsapp_disabled, whatsapp_in_appeal, or whatsapp_reinstated

reasonCode

Rejection/pause reason code (e.g. whatsapp_incorrect_category, whatsapp_abusive_content), or null if approved

reasonDescription

Human-readable explanation from Meta, or null

Rejection reason codes

reasonCode
Description

whatsapp_scam

Meta identified the template as a scam attempt

whatsapp_invalid_format

Invalid format (often a duplicate template name on the same WABA)

whatsapp_incorrect_category

Template content does not match the specified category

whatsapp_promotional

Rejected due to inappropriate promotional content

whatsapp_tag_content_mismatch

Submitted content does not match the tag

whatsapp_abusive_content

Rejected due to abusive or inappropriate content

whatsapp_fallback

Rejected due to fallback policy violation

whatsapp_none

No specific reason provided by Meta; check reasonDescription for details

unknown

Unrecognized reason; check reasonDescription for the raw platform reason

Example: rejected template


7 -- Update a Template

After creating a template, you may need to modify its content -- for example, to fix a typo, change the body text, add a locale, or adjust blocks after a rejection. The update method depends on the template's current status.

Update strategy by status

Current status
Method
Result

draft

PATCH the existing template

Same template ID is updated in-place

active, inactive, pending

POST a new template version

New template ID is returned; previous version remains unchanged

circle-info

Always check the template status first (step 6) before deciding which update method to use. Templates that have already been submitted to Meta (active, inactive, pending) cannot be patched -- you must create a new version.

Updating a draft template (PATCH)

If the template has not yet been activated (status is draft), use PATCH to update it in-place. The template keeps its existing ID.

Update ChannelTemplate

patch
Authorizations
HTTPRequired

Uses the Authorization header: 'AccessKey ' followed by your access key token (e.g., 'Authorization: AccessKey AbCdEfGhIjKlMnOpQrStUvWxYzAbCdEfGhIj')

Path parameters
workspaceIdstringRequired
projectIdstringRequired
channelTemplateIdstringRequired
Body
defaultLocaleall of · nullableOptional
string · enumOptionalExample: enPossible values:
descriptionstringOptional
forceUpdatebooleanOptional

If true and template is already published, a new template will be created with the new parameters and activated.

statusstring · enum · nullableOptionalPossible values:
Other propertiesanyOptional
Responses
chevron-right
200

Updated

application/json
idstring · uuidRequired
projectIdstring · uuidRequired
statusstring · enumOptionalPossible values:
descriptionstringOptional
defaultLocalestring · enumOptionalExample: enPossible values:
createdAtstring · date-timeRequired
updatedAtstring · date-timeOptional
isCloneablebooleanOptional
editorIdstring · uuidOptional
editorTypestringOptional
publisherIdstring · uuidOptional

The ID of the user that last published this ChannelTemplate.

publisherTypestring · stringOptional
shortLinksobject · nullableOptional
clonedFromstring · uuid · nullableOptional

The ID of the template that this template was cloned from. This field is only present if this template was cloned from another template.

metricsobjectOptional

Metrics for this template.

patch
/workspaces/{workspaceId}/projects/{projectId}/channel-templates/{channelTemplateId}

The request body is the same as the create request (step 4), except you must omit supportedPlatforms.

Example request:

Example response:

The response returns the full updated template with the same id:

After patching a draft, proceed to step 5 (Activate) to submit it to Meta.

Creating a new version of an active or inactive template (POST)

If the template has already been activated -- regardless of whether it was approved (active), rejected (inactive), or is still under review (pending) -- you cannot patch it. Instead, create a new version by POSTing to the same endpoint used in step 4.

The request body is identical to the create request in step 4.

Example response:

The response returns a new template with a new id. Use this new ID for subsequent activation and status checks.

circle-exclamation

After creating the new version, proceed to step 5 (Activate) to submit it to Meta for approval.

Meta rate limits for template updates

Meta enforces rate limits on template resubmissions for locales that have already been approved:

  • 24-hour cooldown -- after a template locale is approved, you must wait at least 24 hours before resubmitting that locale with changes.

  • 10 edits per 30 days -- each approved template locale can only be resubmitted up to 10 times within a rolling 30-day window.

These limits apply per WABA, per template name, per locale. They do not apply to draft templates or to the initial submission of a new locale.

circle-exclamation
  1. Check current status -- GET /workspaces/{workspaceId}/projects/{projectId}/channel-templates/{channelTemplateId}

  2. Choose update method:

    • If status is draftPATCH the template (omit supportedPlatforms from the body)

    • If status is active, inactive, or pendingPOST a new version (include supportedPlatforms)

  3. Activate the template -- submit the new or updated template to Meta (step 5)

  4. Monitor approval -- check the template status (step 6) or set up webhooks


Template Lifecycle and Webhooks

After activation, templates move through several states as Meta reviews and monitors them. To receive real-time notifications when template status, quality rating, or approval state changes, set up a webhook subscription.

For the full lifecycle diagram, quality rating guidance, and webhook payload examples, see WhatsApp Template Webhooks.


Block Types Reference

The platformContent.blocks array defines the template structure. The block structure varies by template type. See the WhatsApp Template Blocks Reference for all 10 supported template types with complete examples:

Template type
Documentation

Text

Text Template Blocks

Image

Image Template Blocks

File / Video

File & Video Template Blocks

Carousel

Carousel Template Blocks

Catalog

Catalog Template Blocks

Coupon

Coupon Template Blocks

Flow

Flow Template Blocks

Multi-Product

Multi-Product Template Blocks

Limited Time Offer

Limited Time Offer Template Blocks

Authentication

Authentication Template Blocks


Last updated

Was this helpful?