Recipe: send WhatsApp notifications and templates from your website
Last updated: 11 November 2026 · 10 min read
This recipe sends WhatsApp messages to customers from your website, mobile app or CRM: verification codes, orders, deliveries, reminders. Every message is written to the customer's Clomni conversation, so when the customer replies the agent sees what was sent before.
Steps
-
1
What you get
- A WhatsApp notification with one request from your system. Clomni finds or creates the contact and the conversation itself.
- Free text while the 24 hour window is open, an approved template when it is closed. Clomni checks the window itself.
- The message status
sent,delivered,read,failed, also by webhook. - Notifications do not fill the agents' "Open" list: by default the conversation stays resolved and opens when the customer replies.
-
2
Two kinds of WhatsApp
- WhatsApp Business API (Cloud): connected with a Meta account. It has the 24 hour window; outside it only an approved template goes out, and Meta charges for it. The
/v1/whatsapp/*endpoints work only with this kind. - WhatsApp QR: the WhatsApp on a phone is linked by QR code. No window and no templates, but a number that sends a lot can be blocked.
/v1/whatsapp/messagesdoes not send from a QR number. On QR you only reply in an open conversation (step 6).
- WhatsApp Business API (Cloud): connected with a Meta account. It has the 24 hour window; outside it only an approved template goes out, and Meta charges for it. The
-
3
Scopes you need
messages:send.template(high risk): send templates and list them.messages:send(high risk): send text. When you sendtexttogether withfallback_template, both scopes are needed.channels:read(low risk): the list of WhatsApp numbers and theirchannel_id.messages:read(medium risk): check the window and the message status, and themessage.*webhooks.
In the review form describe the daily volume, who creates the messages (a person, a system, AI) and how you collect consent for marketing messages: Review: checking scopes and rejection reasons.
The WhatsApp API that works with a profile API key (Get started with the WhatsApp API: API key, account_id and channel_id) is a separate product: its paths are
/v1/accounts/{account_id}/whatsapp/.... With a developer token the path has no workspace ID:/v1/whatsapp/.... Bulk sending (bulk_messages) exists only in that API. -
4
1. Find the channel
curl "https://api.clomni.ai/v1/whatsapp/channels" \ -H "Authorization: Bearer clomni_pat_xxx"
Each number in the response has a
channel_idand asendablefield.sendable: falseis a QR number; this API does not send from it. -
5
2. Pick a template
curl "https://api.clomni.ai/v1/whatsapp/templates?channel_id=5" \ -H "Authorization: Bearer clomni_pat_xxx"
Only templates approved by Meta (
APPROVED) come back.example_parametersis a ready skeleton of the parameters the template expects: copy it and replace the values with your own data. The API does not create templates: create the template in Meta, then sync templates in the WhatsApp channel settings in the dashboard.synced_atshows when the list was last fetched. -
6
3. Understand the 24 hour window
The customer opens the window: for 24 hours after they write to you, any text goes out. A template you send does not open the window; the customer's reply or a tap on a quick reply button in the template does. If you send several notifications, put a quick reply button in the first template. To check in advance:
curl "https://api.clomni.ai/v1/whatsapp/messages/window?channel_id=5&phone_number=%2B994501234567" \ -H "Authorization: Bearer clomni_pat_xxx"
open: falsewithlast_inbound_at: nullmeans this number has never written to you: the first message must be a template. -
7
4. Send
Verification code (template):
curl -X POST "https://api.clomni.ai/v1/whatsapp/messages" \ -H "Authorization: Bearer clomni_pat_xxx" \ -H "Content-Type: application/json" \ -d '{"channel_id": 5, "phone_number": "+994501234567", "template": {"name": "verification_code", "language": "az", "parameters": {"body": {"1": "483920"}}}, "contact": {"name": "Leyla Hasanova", "identifier": "crm-10422"}, "source_reference": "otp-10422-1794120000"}'Delivery notification (text if the window is open, template if it is closed):
curl -X POST "https://api.clomni.ai/v1/whatsapp/messages" \ -H "Authorization: Bearer clomni_pat_xxx" \ -H "Content-Type: application/json" \ -d '{"channel_id": 5, "phone_number": "+994501234567", "text": "Your parcel AZ-10422 is with the courier.", "fallback_template": {"name": "cargo_status", "language": "az", "parameters": {"body": {"1": "AZ-10422", "2": "with the courier"}}}}'sent_asin the response says which one went out:session(text) ortemplate. If the window is closed and there is nofallback_template, nothing goes out and 422 comes back, so a paid message never leaves without you knowing.source_referenceis your own unique key. Within 24 hours a request with the same key does not create a new message but returns the first one: the customer does not get two codes and Meta is not paid twice.conversation_statusdefaults toresolved: the conversation does not land in the agents' list. Sendopenif an agent should see it right away.- The number must be international, 8 to 15 digits. Spaces, hyphens and
+are removed.0501234567is wrong because it has no country code. - Template parameters:
{"1": "..."}or the names you gave in Meta for the body,media_urlandmedia_type(image,video,document) for the header,urlorcopy_codefor buttons.
-
8
5. Track the status
status: "sent"means Meta accepted the message, not that it arrived. To read the latest state:curl "https://api.clomni.ai/v1/whatsapp/messages/918234" \ -H "Authorization: Bearer clomni_pat_xxx"
Statuses:
sent,delivered,read,failed(the reason is inexternal_error). Instead of asking about every message, subscribe to themessage.updatedwebhook. Addmessage.createdto get the customer's reply. See App webhooks and events: setup, topics, signature verification. -
9
6. Reply in an open conversation (Cloud and QR)
To write inside a conversation use
POST /v1/conversations/{conversation_id}/messages, where{conversation_id}is the number the dashboard shows. This path works on both Cloud and QR. On Cloud, if the window is closed, sendtemplate_params, which needsmessages:send.template. Sending on this path happens in the background: if the message cannot go out it becomesfailedlater, with the reason incontent_attributes.external_error. For automatic notifications the path in step 4 is simpler. -
10
Common mistakes
/v1/whatsapp/messagesis called for a QR number and 422 "This API requires a WhatsApp Cloud API inbox" comes back. Checksendable.- The template name or language code is wrong, or the template was not synced in the dashboard: 422 "No approved template named".
- The number of parameters does not match the template and Meta rejects the message: the status becomes
failed. Compare withexample_parameters. - A send is repeated without
source_referenceand the customer gets two codes. sentis read as "delivered". Delivery shows asdelivered.- On QR, 463 or
recipient_restrictedcomes back and is retried automatically. Do not retry: WhatsApp counts each attempt separately and extends the restriction. - A first message is sent to a contact whose number is hidden (
identifierends with@lid). The customer has to write first or share their number. - Marketing goes out without consent. Complaints lower the number's quality and its daily limit.
All message endpoints: Scopes and endpoints: conversations and messages.