# Send WhatsApp Template

Reach a WhatsApp customer with an approved Meta template regardless of whether the messaging window is open, checked for approval and marketing consent before anything is sent.

## Getting here

**Automate → Workflows**, open a workflow, click **+** on the canvas, then pick **Send WhatsApp Template** under **Add Steps**.

## Before you start

- An **owner**, **admin** or **agent** can add this step and save the workflow. Publishing that workflow — the thing that makes it run on live conversations — is an **owner** or **admin** action.
- Building and running workflows depends on your plan; see [pricing](/pricing).
- The template you pick must already be **approved by Meta** on this WhatsApp number — approval happens outside Inchat, on Meta's side, and can take from minutes to a day or more.

## Set up

1. Open the workflow and click **+** where the template belongs.
2. Pick **Send WhatsApp Template**.
3. Choose a template from the list — every template this workspace has synced as approved, not only the ones approved for the number this workflow sends from.
4. Click **+ Add variable** once per `{{1}}`, `{{2}}` … slot the template body actually has, in order, and fill each one in.
5. Optional, under **Advanced Settings**: turn on **Add Message Failure Branch** for a path to run when the template is not approved, consent is missing, or the consent lookup itself fails.
6. Save the step, then publish the workflow.

## Fields

| Field | What it means | Default | Limits |
| --- | --- | --- | --- |
| Template | The approved template to send, by name and language. | — | Lists every template this workspace has synced as approved — not filtered to the WhatsApp number the workflow actually sends from. |
| Template variables | One value per `{{n}}` placeholder in the template's approved body text, added by hand with **+ Add variable**, one row per slot, in order. | — | Nothing here reads the template's real placeholder count — adding too few or too many rows is on the author to catch. Editing the template's wording on Meta's side can also shift what belongs in each slot without this step's rows changing to match. A row left blank is DROPPED on save, not sent as an empty value — every row after it silently shifts up one slot, so a blank `{{2}}` quietly sends what you meant for `{{3}}` into `{{2}}`'s place. |
| Add Message Failure Branch | Adds an **onFailure** arm that runs instead of the steps that would otherwise follow, when the template is not approved or the send is skipped for consent. | off | Without it, a failed or skipped send is recorded and the run moves on to the next step as if nothing happened. |

## How it works

- Unlike **Send a Message**, this step never checks whether the 24-hour messaging window is open — reopening a closed window is the reason it exists.
- Before anything reaches Meta, the step runs two checks in order: first that the template is still approved (a template can be paused, disabled, rejected, still pending review, or not yet synced to Inchat at all), then — only for a template whose Meta-assigned category is marketing, or whose category could not be read — that this contact has given marketing consent and has not opted out. A utility or authentication template skips the consent check.
- A blocked contact is refused on every category, including utility and authentication — blocking is checked before the category is even read. An opt-out (a WhatsApp STOP, or consent withdrawn) only stops a marketing-category send; a utility or authentication template still reaches an opted-out contact.
- The consent check reads the contact's CURRENT state at the moment of sending, not whatever it was when the workflow started — a marketing chase queued for later re-reads the contact's opt-out, a fresh **No** answer, or a block that happened while it waited.
- Consent is folded across every contact record in this workspace that shares this contact's phone number, so a withdrawal recorded on one of those rows is not undone by a stale grant on another.
- Once both checks pass, the template is sent with your variables filling its `{{1}}`, `{{2}}` … slots in body order, and the send is recorded on the conversation as a reply from the workflow.

## When it fails

- Template not approved: the step fails before any send is attempted. The execution log carries Inchat's own text built from the template's stored status — **is PAUSED/DISABLED/REJECTED/PENDING — Meta will not deliver it**, or, if this workspace never synced that name and language at all, **is not in the synced cache yet — sync templates and try again.** Either way this is not a message Meta itself sent back.
- Marketing consent required and missing: the step is skipped rather than sent — logged as **Skipped: the contact has not agreed to marketing messages, and this is a marketing template.** No message reaches Meta, and no message row is recorded.
- The contact opted out (marketing category only), or is blocked (every category): skipped the same way, logged as **Skipped: the contact opted out of marketing messages or is blocked.** — one shared reason text for both cases, even though only a block also stops a utility or authentication template.
- Consent could not be checked (a lookup problem): the step fails closed with **Could not check the contact's marketing consent. Please try again.** — the same as never sending, not the same as sending anyway.
- With **Add Message Failure Branch** off, none of the above stop the rest of the run — steps placed after it, such as a tag or a close, still happen on a conversation that received no template. With it on, the branch's own steps run instead, and nothing after the branch runs on this path — a skip counts as a failure here exactly like an unapproved template does.

## Limits

- The **Template** picker lists every template this workspace has synced as approved, not only the ones approved for the WhatsApp number this workflow actually sends from — the send-time check is scoped to that one number, so a template approved elsewhere in the workspace but not on this number fails at send with a not-approved or not-synced reason, even though the drawer offered it.
- It cannot create, edit or submit a template for approval — that happens in the templates section of the product, outside this step.
- It never checks the 24-hour window, so it will also fire — and pass the same consent check — on a conversation whose window is still open; it is not the only step that can reach a WhatsApp customer past that window either, since **Start a WhatsApp Chat** also sends an approved template on a thread it finds or creates.
- A blank row in **Template variables** is dropped on save, not sent as an empty value — every later row shifts up to fill the gap, so a mid-list blank silently misdelivers every variable after it into the wrong slot.
- It does not ask the customer for consent. Consent is only ever recorded by **Ask for Marketing Consent** or elsewhere in the product; this step only reads what is already on record.
- The consent check applies to marketing-category templates (and any template whose category this workspace has not synced). A utility or authentication template — an order update, a one-time code — reaches a contact who has opted out of marketing but not a contact who is blocked; a block stops every category.

## Best practices

- Put this step, not **Send a Message**, on any path that can run after a day of customer silence — a **conversation_inactive** or **order_*** reopen, an event or booking reminder past its window.
- Give a marketing template's flow a **Condition** on marketing consent before this step where it matters to know in advance, rather than relying only on the skip — the skip protects the send, it does not tell the rest of the flow what happened.
- Keep the variable count matched to the template's current approved body; editing a template's wording on Meta's side without checking this step's variable list is a common cause of a wrong value landing in the wrong slot.

## Use cases

- A payment reminder three days after **order_created**, sent as a utility template so it reaches the customer with no marketing consent needed.
- A win-back message on **conversation_inactive**, gated on marketing consent by the send path itself — no separate Condition needed for the consent part.
- Re-opening a chat after a **booking_reminder_due** trigger fires outside the messaging window.

## FAQ and troubleshooting

### Can this step message a WhatsApp customer whose 24-hour window closed days ago?

Yes — that is what it is for. It never checks the messaging window, unlike Send a Message.

### The step didn't send and there's no error the customer would notice. What happened?

Either the template was not approved at the moment of sending, or — for a marketing template — the contact has not given marketing consent or opted out, or the contact is blocked. All three are visible in the workflow's Activity tab, and none sends anything to the customer, so nothing looks wrong on their side either.

### If a customer opts out after this step's workflow has already started (e.g. during a Wait), will it still send?

No, for a marketing template. Consent is checked live at the moment of sending, not when the run started, so an opt-out recorded during the wait blocks a marketing template that follows it. A utility or authentication template is unaffected by an opt-out either way.

### Do utility templates need marketing consent too?

No. Only a template whose category is marketing — or one whose category this workspace has not synced — is checked for consent. A utility or authentication template still reaches a contact who opted out of marketing, but not one who is blocked — a block stops every category.

## Related

- [Send a Message](https://inchat.inseller.my/help/workflows/send-a-message)
- [Ask for Marketing Consent](https://inchat.inseller.my/help/workflows/ask-for-marketing-consent)
- [Start a WhatsApp Chat (new number)](https://inchat.inseller.my/help/workflows/start-a-whatsapp-chat)
- [Workflow triggers](https://inchat.inseller.my/help/workflows/workflow-triggers)
- [Condition](https://inchat.inseller.my/help/workflows/condition)
- [Workflows: how a flow runs](https://inchat.inseller.my/help/workflows/workflows-overview)

---

Source files: `src/lib/workflows/ai-builder/spec.ts`, `src/lib/workflows/canvas-model.ts`, `src/components/workflows/WorkflowStepConfigDrawer.tsx`, `src/lib/workflows/dispatch-send.ts`, `src/lib/workflows/template-consent-gate.ts`, `src/lib/public-api/outbound-template.ts`, `src/lib/channels/whatsapp-templates.ts`, `src/lib/workflows/engine-message-actions.ts`, `src/lib/workflows/engine.ts`, `src/lib/access/permissions.ts`
