Skip to main content

Meta Template Library

Meta maintains a catalog of ready-made WhatsApp message templates — the Template Library. Every entry has already been written and reviewed by Meta, in many languages. When you adopt one without changing the wording, it is created in your WhatsApp Business Account already APPROVED, so you can send it immediately instead of waiting out a review.

This is the fastest path from "channel connected" to "first template sent", and it is what powers the one-click template flow in the SendSeven app.

Library template (unchanged)Template you write yourself
ApprovalInstant — created as APPROVEDReview, usually minutes, up to 24 hours
WordingFixed by MetaYours
CategoriesUTILITY, AUTHENTICATIONUTILITY, MARKETING, AUTHENTICATION
ButtonsMeta's, optionally re-pointed at your URLs / phone numbersYours
Editing forfeits instant approval

Changing the body, header or footer of a library entry makes it your template: it goes through Meta's normal review like any other new template. You can still rename it and point its buttons at your own destinations while keeping instant approval — those are not content changes.

Required Scopes

EndpointScopes
GET /whatsapp-templates/librarychannels:read
POST /whatsapp-templates/library/adoptchannels:admin or messages:create

messages:create is accepted for adoption on purpose. The main use case is an agent who has no approved template and needs one to open a conversation — gating a Meta-curated, pre-approved action behind channel administration would break exactly the flow it exists for.

Browse the Library

GET /api/v1/whatsapp-templates/library

Required Scope: channels:read

Query Parameters

ParameterTypeDefaultDescription
channel_idstringRequired. WhatsApp channel whose WABA credentials are used to read the catalog
languagestringMeta language code, e.g. en_US. Omit for all languages
searchstringFree-text search across name, body, topic and use case
topicstringe.g. PAYMENTS
usecasestringe.g. LOW_BALANCE_WARNING
industrystringe.g. FINANCIAL_SERVICES
namestringExact library template name
limitinteger100Max entries to return (1–500)
curl -X GET "https://api.sendseven.com/api/v1/whatsapp-templates/library?channel_id=71a1351f-4d6a-4444-9c6b-1cc8d63d7408&language=en_US&search=delivery&limit=20" \
-H "Authorization: Bearer s7_api_a1b2c3d4e5f6789012345678abcdef00" \
-H "Content-Type: application/json"

Response

{
"items": [
{
"id": "1055577921234567",
"name": "delivery_update_1",
"language": "en_US",
"category": "UTILITY",
"topic": "ORDER_MANAGEMENT",
"usecase": "DELIVERY_UPDATE",
"industry": ["E_COMMERCE"],
"header": null,
"body": "Your order {{1}} is on its way and should arrive by {{2}}.",
"footer": null,
"body_params": ["ORD-5678", "Feb 15"],
"body_param_types": ["order_id", "date"],
"buttons": [
{
"type": "URL",
"text": "Track order",
"url": "https://www.example.com/track",
"phone_number": null,
"otp_type": null
}
],
"already_added": false,
"requires_input": true
}
],
"total": 34,
"facets": {
"languages": ["en_US", "de_DE", "es_ES"],
"topics": ["ORDER_MANAGEMENT", "PAYMENTS"],
"usecases": ["DELIVERY_UPDATE", "PAYMENT_DUE"],
"industries": ["E_COMMERCE", "FINANCIAL_SERVICES"]
},
"language": "en_US",
"stale": false,
"warning": null
}

total is the number of matches found before limit was applied. facets are derived from the matched result set (Meta has no facets endpoint), so they are exactly the filter values that would return something.

Two fields are added by SendSeven, not by Meta:

FieldMeaning
already_addedThis tenant already has a template with the same name and language on this channel. Adopting again is a no-op (see Idempotency)
requires_inputAt least one button needs a value only you can supply — a link URL or a phone number. Meta's catalog ships placeholder destinations (example.com, sample numbers) for those, so you must pass button_inputs when adopting. false means the entry can be adopted with no extra input

Caching, staleness and 429s

Meta rate-limits its template endpoints aggressively, while the library catalog is global and near-static. SendSeven therefore caches it server-side for 12 hours, and keeps a longer-lived copy (14 days) purely as a fallback.

If Meta is unreachable or rate-limits the call and a fallback copy exists, the request still succeeds — with stale: true and a human-readable warning:

{
"items": ["..."],
"total": 34,
"stale": true,
"warning": "Meta is rate-limiting template requests, so this list may be slightly out of date."
}

Treat that as a soft hint ("may be out of date"), not an error. Only when there is no cached copy at all does the endpoint fail:

StatusCause
400Channel is not a usable WhatsApp channel (missing WABA or token)
429Meta rate-limited us and nothing was cached
503Meta transiently unreachable and nothing was cached (retryable)
502Meta returned a non-retryable error

Adopt a Library Template

POST /api/v1/whatsapp-templates/library/adopt

Required Scope: channels:admin or messages:create

Request Body

FieldTypeRequiredDescription
channel_idstringYesWhatsApp channel whose WABA receives the template
library_template_namestringYesThe name of the library entry, e.g. delivery_update_1
languagestringNoMeta language code to create it in. Default en_US
categorystringNoDefaults to the library entry's own category (UTILITY / AUTHENTICATION)
namestringNoName for the created template. Defaults to library_template_name. Normalised to lowercase and underscores
button_inputsarrayNoYour own button destinations. Omit to accept the library entry's example values — see below
snapshotobjectNoThe library entry exactly as your client displayed it, used as a content fallback if Meta rate-limits the confirmation lookup

One-click adoption

For any entry with requires_input: false, the whole call is four fields:

curl -X POST "https://api.sendseven.com/api/v1/whatsapp-templates/library/adopt" \
-H "Authorization: Bearer s7_api_a1b2c3d4e5f6789012345678abcdef00" \
-H "Content-Type: application/json" \
-d '{
"channel_id": "71a1351f-4d6a-4444-9c6b-1cc8d63d7408",
"library_template_name": "delivery_update_1",
"language": "en_US"
}'

Response (201 Created)

{
"success": true,
"id": "tpl_abc123",
"template_id": "1234567890123456",
"name": "delivery_update_1",
"language": "en_US",
"status": "approved",
"category": "UTILITY",
"already_existed": false,
"error": null,
"error_code": null,
"error_subcode": null,
"error_is_retryable": false,
"fbtrace_id": "A1bCdEfGhIjKlMnOpQ"
}

id is the SendSeven template ID you send with; template_id is Meta's. An unchanged library template comes back approved and is stored that way — SendSeven deliberately does not re-sync to confirm it, because sync is the rate-limited call and your next action is to send.

On failure success is false and the response carries the parsed Graph error context (error, error_code, error_subcode, error_is_retryable, fbtrace_id); the HTTP status reflects whether a retry is worthwhile.

Button inputs

Meta's catalog ships example button destinations. Entries whose buttons open a link or dial a number are flagged requires_input: true and need one button_inputs entry per such button, in the same order as the entry's buttons of that type. QUICK_REPLY buttons take no input — Meta fills them from the library definition.

FieldTypeDescription
typestringURL, PHONE_NUMBER, OTP, MPM, CATALOG, FLOW, VOICE_CALL, APP
url.base_urlstringThe URL the button opens. May contain a single {{1}} variable
url.url_suffix_examplestringRequired when base_url contains a variable: the full example URL with the variable filled in
phone_numberstringFor PHONE_NUMBER buttons, in E.164 format
otp_typestringCOPY_CODE, ONE_TAP or ZERO_TAP for authentication templates

A URL button pointing at your own tracking page, with the order ID as the variable part:

curl -X POST "https://api.sendseven.com/api/v1/whatsapp-templates/library/adopt" \
-H "Authorization: Bearer s7_api_a1b2c3d4e5f6789012345678abcdef00" \
-H "Content-Type: application/json" \
-d '{
"channel_id": "71a1351f-4d6a-4444-9c6b-1cc8d63d7408",
"library_template_name": "delivery_update_1",
"language": "en_US",
"name": "delivery_update_shop",
"button_inputs": [
{
"type": "URL",
"url": {
"base_url": "https://shop.example.com/track/{{1}}",
"url_suffix_example": "https://shop.example.com/track/ORD-5678"
}
}
]
}'

A phone-number button:

{
"button_inputs": [
{ "type": "PHONE_NUMBER", "phone_number": "+4930123456789" }
]
}

Idempotency

Adopting a template the tenant already has is a no-op: the existing row is returned with already_existed: true and HTTP 200 instead of 201. Nothing is sent to Meta, so re-running an adoption after a network timeout is safe.

Send the Adopted Template

An adopted library template is an ordinary SendSeven template. Use the id from the adopt response and fill its {{1}}, {{2}} … placeholders exactly as with any positional template:

curl -X POST "https://api.sendseven.com/api/v1/whatsapp-templates/tpl_abc123/send" \
-H "Authorization: Bearer s7_api_a1b2c3d4e5f6789012345678abcdef00" \
-H "Content-Type: application/json" \
-d '{
"contact_id": "contact_xyz789",
"channel_id": "71a1351f-4d6a-4444-9c6b-1cc8d63d7408",
"language": "en_US",
"variable_values": ["ORD-5678", "Feb 15, 2026"]
}'

The library entry's body_params are Meta's example values, index-aligned with the placeholders, and body_param_types names what each placeholder is (order_id, date, …) when Meta provides it — useful for pre-filling or mapping your own fields.

See Send a Template Message for the full send reference, including media headers and button parameters.

End-to-End Flow

1. GET  /whatsapp-templates/library?channel_id=…&language=en_US
→ pick an entry; note `requires_input`
2. POST /whatsapp-templates/library/adopt
→ { "id": "tpl_abc123", "status": "approved" }
3. POST /whatsapp-templates/tpl_abc123/send
→ template delivered, 24-hour window opens when the customer replies
Billing at Meta

Sending templates is billed by Meta to your WhatsApp Business Account, so a payment method must be on file there — instant approval does not change that. Replying to an inbound message inside the 24-hour window needs no payment method at Meta.

Next Steps