Send a WhatsApp message
send_whatsapp_messageSend a WhatsApp message to a customer using an approved template or free-form reply. Requires confirmation and validates template variables before sending to avoid Meta refusal.
Instructions
Send a WhatsApp message from one of the brand’s registered numbers to a customer. TWO KINDS, and which one is legal depends on time: pass template (an APPROVED template name) to START a conversation — the only thing WhatsApp accepts outside the 24-hour customer-service window — or text for a free-form reply INSIDE that window, which opens only when the customer messages the business first. Hermoso does not receive WhatsApp webhooks yet, so it CANNOT see whether that window is open: a free-form message is sent optimistically and Meta refuses it with a re-engagement error if it is closed, which the reply explains rather than reporting as a broken connection. THIS REACHES A REAL PERSON’S PHONE AND META BILLS THE BUSINESS for the conversation, so it is confirm-gated: show the user the exact message and the recipient, get an explicit yes, then call again with confirm:true. WhatsApp policy REQUIRES the business to hold the recipient’s opt-in first. An unapproved template is refused BEFORE the send, against the status Meta holds. ACCEPTED IS NOT DELIVERED — the reply reports what Meta accepted, and delivery arrives on a webhook we do not receive, so never tell the user it was delivered. THE VARIABLE COUNT IS CHECKED BEFORE ANYTHING IS DISPATCHED: Hermoso reads the template’s own components back from Meta and refuses a payload that supplies the wrong number of values, naming exactly what is missing — for free, before a real phone is involved, instead of Meta answering 132000 after the attempt. It refuses only what it can prove; anything it cannot determine is sent for Meta to judge. 0 Hermoso credits.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | the recipient in full international form, e.g. +14165550142 | |
| text | No | a free-form message — only lands INSIDE the 24-hour window | |
| wabaId | No | the account the template’s review status is read from. Optional — it defaults to the account that owns phoneNumberId, and a wabaId naming a DIFFERENT account is refused rather than silently preferred | |
| confirm | No | REQUIRED true — this sends a real message to a real phone and Meta bills the business for it | |
| language | No | which language of that template, e.g. en_US. Omitted, Hermoso uses the first one it finds and reports which. | |
| template | No | an APPROVED template name — required to start a conversation outside the 24-hour window | |
| components | No | the template’s variable values, in Meta’s component form. The count must match the {{1}}, {{2}} placeholders exactly. Hermoso checks this against the template’s real components before dispatching and refuses a provable mismatch by name. A media header needs its own component holding the link even though it carries no {{n}}, and a carousel needs one entry per card. | |
| phoneNumberId | Yes | WHICH NUMBER IT SENDS FROM — from list_whatsapp_accounts (a WABA can have several) |