List this account's utility templates, newest change first. Pass status and updatedAfter to poll for just what moved since your last call, and starting_after with the last id to page. Marketing templates are not listed, since /v1/messages will not send them.
The last id from the previous page. Results continue after it.
status
pending | processing | approved | rejected
no
Return only templates in this state.
updatedAfter
object
no
Only templates changed since this instant, which is what makes polling cheap.
Response 200
Field
Type
Description
data
object[]
This page of templates.
has_more
boolean
Another page exists. Pass the last id in data as starting_after.
Errors
Returns 400, 401, 403, 429, 503. Every one carries the standard envelope — branch on code, not the status. See Errors.
Create a template
Create a utility template and submit it to Meta in one call. There is no draft state. Returns processing; poll GET /v1/templates/\{id\} until it is approved or rejected, then send with the returned tpl_ id. A media header takes a med_ id from POST /v1/media/. Requires an Idempotency-Key, since a create permanently claims the name on your WhatsApp Business Account.
await msg.templates.create({ name: "order_shipped", category: "UTILITY", language: "en_US", body: "Hi {{1}}, your order {{2}} has shipped.",});
Body
Field
Type
Required
Description
name
string
yes
Lowercase letters, digits and underscores. Claimed permanently at Meta — a deleted name stays reserved for about 30 days.
category
UTILITY
yes
Utility only. Marketing templates cannot be created, listed or sent through the API.
language
string
yes
Meta's language code, not ours.
body
string
yes
The message text. Use \{\{1\}\}, \{\{2\}\} for placeholders.
variables
object[]
no
An example value per placeholder. Meta rejects a template whose examples are missing.
header
object
no
A text or media header. Omit it entirely for no header.
Only an approved template can be sent. pending and processing are waiting on Meta; rejected carries a rejectionReason.
category
MARKETING | UTILITY
Meta re-categorises on approval, so this can differ from what was submitted.
language
string
Meta's language code.
body
string
The message text, with \{\{n\}\} placeholders.
variables
object[]
One entry per placeholder in the body.
header
object
Null when the template has no header.
footer
string
Null when the template has no footer.
rejectionReason
string
Why Meta refused it. Null unless status is rejected.
approvedAt
string (ISO 8601)
Null until Meta approves it.
createdAt
string (ISO 8601)
When the template was created here.
updatedAt
string (ISO 8601)
Last change, including a status change from Meta.
Errors
Returns 400, 401, 403, 404, 409, 429, 502, 503. Every one carries the standard envelope — branch on code, not the status. See Errors.
Get a template
Fetch one template's approval status. processing means Meta is still reviewing; rejected carries the reason. Covers any template on the account, including one Meta re-classified as marketing, which the list omits.
Only an approved template can be sent. pending and processing are waiting on Meta; rejected carries a rejectionReason.
category
MARKETING | UTILITY
Meta re-categorises on approval, so this can differ from what was submitted.
language
string
Meta's language code.
body
string
The message text, with \{\{n\}\} placeholders.
variables
object[]
One entry per placeholder in the body.
header
object
Null when the template has no header.
footer
string
Null when the template has no footer.
rejectionReason
string
Why Meta refused it. Null unless status is rejected.
approvedAt
string (ISO 8601)
Null until Meta approves it.
createdAt
string (ISO 8601)
When the template was created here.
updatedAt
string (ISO 8601)
Last change, including a status change from Meta.
Errors
Returns 400, 401, 403, 404, 429, 503. Every one carries the standard envelope — branch on code, not the status. See Errors.
Update a template
Fix a template Meta rejected and resubmit it. Only a pending or rejected template may be edited — Meta freezes content once a template is approved or in review, so anything else is a 409. Omitted fields keep their current value.
await msg.templates.update("tpl_3b9f1c2d4e5a6b7c8d9e0f1a2b3c4d5e", { name: "order_shipped", language: "en_US", body: "Hi {{1}}, your order {{2}} has shipped.",});
Path parameters
Field
Type
Required
Description
id
string
yes
A tpl_ id from GET /v1/templates.
Body
Field
Type
Required
Description
name
string
no
Lowercase letters, digits and underscores. Claimed permanently at Meta — a deleted name stays reserved for about 30 days.
category
UTILITY
no
Utility only. Marketing templates cannot be created, listed or sent through the API.
language
string
no
Meta's language code, not ours.
body
string
no
The message text. Use \{\{1\}\}, \{\{2\}\} for placeholders.
variables
object[]
no
An example value per placeholder. Meta rejects a template whose examples are missing.
header
object
no
A text or media header. Omit it entirely for no header.
Only an approved template can be sent. pending and processing are waiting on Meta; rejected carries a rejectionReason.
category
MARKETING | UTILITY
Meta re-categorises on approval, so this can differ from what was submitted.
language
string
Meta's language code.
body
string
The message text, with \{\{n\}\} placeholders.
variables
object[]
One entry per placeholder in the body.
header
object
Null when the template has no header.
footer
string
Null when the template has no footer.
rejectionReason
string
Why Meta refused it. Null unless status is rejected.
approvedAt
string (ISO 8601)
Null until Meta approves it.
createdAt
string (ISO 8601)
When the template was created here.
updatedAt
string (ISO 8601)
Last change, including a status change from Meta.
Errors
Returns 400, 401, 403, 404, 409, 429, 502, 503. Every one carries the standard envelope — branch on code, not the status. See Errors.
Validate a template
Check a template against our content rules without creating it. Nothing is stored and Meta is not called, so a test key may use it. Returns every issue at once. Passing here does not guarantee Meta will approve — that review is separate.
await msg.templates.validate({ name: "order_shipped", category: "UTILITY", language: "en_US", body: "Hi {{1}}, your order {{2}} has shipped.",});
Body
Field
Type
Required
Description
name
string
yes
Lowercase letters, digits and underscores. Claimed permanently at Meta — a deleted name stays reserved for about 30 days.
category
UTILITY
yes
Utility only. Marketing templates cannot be created, listed or sent through the API.
language
string
yes
Meta's language code, not ours.
body
string
yes
The message text. Use \{\{1\}\}, \{\{2\}\} for placeholders.
variables
object[]
no
An example value per placeholder. Meta rejects a template whose examples are missing.
header
object
no
A text or media header. Omit it entirely for no header.
footer
string
no
Small text under the body.
Response 200
Field
Type
Description
valid
boolean
Whether the template would be accepted for submission.
issues
object[]
Every problem at once, so a template is fixable in one round trip. Empty when valid.
Errors
Returns 400, 401, 403, 409, 429, 503. Every one carries the standard envelope — branch on code, not the status. See Errors.