Skip to content

Documentation

Build with Engage

Connect customer data, business events, and communication channels to build automated journeys with workflows and AI.

Templates

A template is a message Meta approved in advance. It is the only thing you may send to somebody who has not written to you in the last 24 hours.

Writing one

POST /v1/templates

{
  "name": "order_shipped",
  "language": "en_US",
  "category": "utility",
  "body": "Hi {{1}}, order {{2}} is on its way. Reply here with any questions.",
  "examples": ["Ada", "1042"],
  "header": "Your order has shipped",
  "footer": "Reply STOP to opt out",
  "buttons": [
    { "type": "URL", "text": "Track order", "url": "https://track.example.com/{{1}}" },
    { "type": "QUICK_REPLY", "text": "Thanks!" }
  ],
  "urlExample": "NG1042"
}

Owners only. The dashboard does the same under Settings, WhatsApp and templates. Engage checks WhatsApp's rules first and refuses with the problems keyed by field in details: names are lowercase letters, numbers and underscores; variables run {{1}}, {{2}} with none missing; the body may not start or end with a variable; and each variable needs an example, because Meta reviews the template with the examples filled in.

Then it is submitted to Meta, which usually answers pending and decides within minutes to a day - and may move it to a different category.

Header, footer and buttons

All optional. The header is bold text above the message and the footer small grey text below it - each fixed, up to 60 characters. buttons sit under the message: up to three QUICK_REPLY buttons, whose tap comes back to your inbox as the customer's answer; one URL button; and one PHONE_NUMBER button, with the number in phone including the country code. Labels are up to 25 characters.

A website link can end in {{1}} when its ending changes per message - a tracking number, an order id. Give urlExample for Meta's review, and supply the ending as the url variable when you send it.

Image, video and document headers

A header can be a file instead of text - the product photo, a short video, the invoice as a PDF. Upload the file first:

curl -X POST https://api.engentra.io/v1/media   -H "Authorization: Bearer $TOKEN"   -F "file=@summer-bags.png"

JPEG or PNG up to 5 MB, MP4 or 3GP up to 16 MB, PDF up to 16 MB. The answer's id is the file from then on.

To create the template, give headerMediaId instead of header - that file is the sample Meta reviews. Each message then sends its own file, as the header variable: an uploaded file's id, or an https link, such as the product image your store already hosts.

POST /v1/conversations/{id}/reply-template

{
  "name": "new_bags",
  "variables": { "1": "Ada", "header": "3f1c9a52-8d0e-4b8f-9c61-0c2d8e5b7a41" }
}

In a workflow step, header is { "text": "<file id>" } for the same file every time, or { "from": "event.imageUrl" } for a link your website sends with the event. A campaign sends one file to everyone. Location headers are not supported.

Approval arrives on its own - if the webhook field is on

Meta reports the verdict through the app webhook's message_template_status_update field, and Engage updates the template when it arrives. That field has to be subscribed in the Meta App Dashboard. Without it, sync below picks the verdict up.

When Meta moves a template to another category

Meta can re-categorise an approved template - most often utility to marketing, when it reads the wording as promotional. The template then reaches only customers who opted in, and pauses when the number's quality drops. Engage records the move (previousCategory, categoryChangedAt), emails the owners and shows it beside the template. Subscribe the webhook's template_category_update field to hear at once; otherwise the next sync notices.

Sync after every change

POST /v1/templates/sync

Pulls the current set from Meta for this workspace's channel: names, languages, categories, variable counts and approval status - including templates written in WhatsApp Manager. Run it after writing one there, or when an approval has not shown up.

An unsynced template is an invisible failure

A workflow naming a template this workspace has never synced does not fail when you save it. It fails when it runs — possibly a day later, against a real customer — with No template named '…'. Sync from Meta first.

That exact message came out of a live test. Sync first, then build the workflow that uses it.

What you can send

GET /v1/templates

Only approved templates can be sent. The list also carries the category Meta assigned — marketing, utility or authentication — and that is not cosmetic: category decides whether opt-in is required and whether a marketing opt-out blocks the send. Engage API checks it on every send, so a template re-categorised by Meta changes what is allowed without anything in your code changing.

Variables

Templates have fixed text with numbered slots. You supply the values at send time:

starting a conversation

POST /v1/conversations

{
  "to": "+2348012345678",
  "templateName": "order_ready",
  "language": "en_US",
  "variables": { "1": "Ada", "2": "50kg rice" }
}

replying in one

POST /v1/conversations/{conversationId}/reply-template

{
  "name": "order_ready",
  "language": "en_US",
  "variables": { "1": "Ada", "2": "50kg rice" }
}

Note the field is templateName on one and name on the other. Each template in GET /v1/templates lists its variables - every key a send needs, "1", "2" and "url" for a website button whose link ends in a variable - and a sendable flag, which is the one to check rather than reading the approval status yourself.

a template with a tracking button

"variables": { "1": "Ada", "2": "1042", "url": "NG1042" }

The count is validated here before the send, so a missing variable is refused with a message naming the template rather than by Meta, whose rejection names neither.

Next

Conversations →

Reading threads, replying, and opening one with somebody new.

Send yourself one first

curl -X POST https://api.engentra.io/v1/templates/win_back/test   -H "X-API-Key: $ENGAGE_API_KEY"   -H "Content-Type: application/json"   -d '{ "language": "en_US", "variables": { "1": "Ada" } }'

A preview renders what we believe a template says. Only the real message shows what Meta delivers - where the image lands, how the buttons look on a phone, whether the Yoruba wraps - and the first time a business sees that should not be the campaign.

Only to your own team

The number has to be on a member's profile in this workspace, and with none given it goes to yours. That is what lets a test skip the opt-in checks every other send obeys: a colleague who typed their number into their own workspace has consented, and a stranger has not. No customer and no conversation is created, so nobody lands in the customer list by being tested on.

Deleting one

DELETE /v1/templates/win_back

Removes it at Meta and here, in every language - Meta deletes by name, and leaving one language behind would leave a template this workspace believes it can send and Meta does not. Owners only.

Refused while anything still sends it. A live workflow or a scheduled campaign naming a template that no longer exists does not fail now; it fails four steps into a run at two in the morning. The refusal names what is using it. Campaigns and runs that already sent it keep their history.