Create a WhatsApp template
POST/v1/agents/:agentId/connections/:connectionId/whatsapp-templates
x-scope: "whatsapp_templates:write"
x-rate-limit-per-minute: 10
Submits a new template on one of the agent's WhatsApp numbers for Meta's review, the same as
creating it in the dashboard. The answer is 201 with the template, usually pending:
only an approved template can be sent. Follow Meta's review with getWhatsAppTemplate; a
rejected template says why in rejected_reason.
category is marketing, utility or authentication; Meta may file it under another
one, and the answer shows where it went. A marketing or utility template has a body and
may have a header, a footer and buttons. Variables are {{1}}, {{2}}… in order, or
lower-case names such as {{first_name}}, one style for the whole template, and each needs
a sample (body_examples, header.example) for Meta's review. An image, video or document
header needs media_url: an https link to a sample file (JPEG or PNG, MP4, PDF) of up to
16 MB, which Mojeeb downloads once and hands to Meta. It must answer 200 with the file
itself, as redirects aren't followed, with the file's type as its Content-Type, and point
at a public address. An authentication template has only otp:
Meta writes its text, the code and a sentence around it, in the template's language.
Everything Mojeeb can check is checked before Meta sees the template, so a mistake is a
422 naming the field (param); what only Meta can judge comes back as
422 template_rejected with Meta's reason. A name already used in this language is
409 template_name_taken, which is also what a create retried after a lost response
meets: read the list and carry on. Location headers, carousels, limited-time offers, and
catalog and Flow buttons are made in WhatsApp Manager, as Mojeeb can't send them yet. Every call reaches Meta, so this endpoint shares the
templates' budget of 10 requests a minute per key.
Request
Responses
- 201
- 401
- 403
- 404
- 409
- 413
- 422
- 429
- 500
- 503
The template as Meta now holds it, usually pending.
Response Headers
Correlation id for this request — paste into support tickets.
Authentication failed. Single code (invalid_api_key) covers every
sub-case: missing header, wrong scheme, malformed, unknown, revoked or
expired key. The message field disambiguates for humans debugging.
One exception: when the key could not be checked because of a server-side
fault, the status is still 401 but type is internal_error and code
is internal_server_error; retry with backoff.
Response Headers
Correlation id for this request — paste into support tickets.
Authenticated, but not allowed: insufficient_scope (the key lacks the scope in this
operation's x-scope) or agent_not_authorized (the key is limited to other agents).
Response Headers
Correlation id for this request — paste into support tickets.
not_found when the connection isn't one of this agent's channels or isn't a WhatsApp
number; agent_not_found when the agent is not one of your company's agents. endpoint_not_found when an id in the path isn't a UUID.
Response Headers
Correlation id for this request — paste into support tickets.
Nothing was changed. The number first: connection_inactive (disconnected) and
connection_needs_reconnection (Meta no longer accepts its access) need a reconnect in
the dashboard, so retrying won't help. Then the template: template_name_taken (this
name already exists in this language), template_limit_reached (the WhatsApp account has
as many templates as Meta allows), template_status_not_allowed (its status doesn't
allow the change: only an approved, rejected or paused template can be edited, and
only an approved, rejected, paused or pending one can be deleted),
template_edit_limit_reached (Meta's edits for an approved template are used up),
template_in_use_by_broadcast (a broadcast is sending it; try again when it finishes),
template_reserved (Mojeeb's own notifications use it) and
template_delete_locks_name (send acknowledge_name_lock=true).
Response Headers
Correlation id for this request — paste into support tickets.
The request body is larger than 1 MB.
Response Headers
Correlation id for this request — paste into support tickets.
Nothing was submitted. invalid_request_body when the body isn't valid JSON, a field
breaks a limit in its schema, or the template breaks one of Meta's rules Mojeeb checks
first (a part its category doesn't take, a variable without a sample, buttons out of
order); param names the field, such as buttons[1].url.
template_header_media_url_invalid when Mojeeb couldn't download the header's sample
(param: header.media_url; the message says why). template_rejected when Meta refused
the template, or an edit Meta wouldn't take (an approved template's category, a switch of
variable style); the message says why, in Meta's words when Meta refused it.
Response Headers
Correlation id for this request — paste into support tickets.
Per-key rate limit hit. Default is 60/min/key; an endpoint with an
x-rate-limit-per-minute of its own counts in a budget of its own
(today the WhatsApp template endpoints and sendBroadcast, which share one
that allows 10/min/key, and sendConversationMessage, which allows 20/min/key), and its 429
reports that limit in X-RateLimit-Limit. Retry-After tells you when to retry;
X-RateLimit-Reset is the Unix timestamp of the next window.
Per-success-response
X-RateLimit-*headers are a known gap; on 2xx responses these headers are NOT currently emitted. Customers should rely on 429 +Retry-Afterfor backoff signals.
Response Headers
Correlation id for this request — paste into support tickets.
Seconds to wait before retrying.
The per-minute request limit of the endpoint called. Every key has the same limits today.
Remaining requests in the current window. 0 on rejection.
Unix timestamp at which the current window resets.
Unexpected server-side failure. Retry with exponential backoff. If
the failure persists, send us the correlation_id.
Response Headers
Correlation id for this request — paste into support tickets.
A temporary fault; nothing was changed, so retry with backoff. One exception: a template
create, edit or delete that Meta didn't answer in time may still have been made, so read the
template before trying again.
meta_unavailable: Meta didn't return what was asked (an outage, a
timeout or Meta's own rate limit). access_unavailable: Mojeeb
couldn't check this key's access.
Response Headers
Correlation id for this request — paste into support tickets.