
Initial Release - This is my entry for "Community Bounty Program "Idea to Application" — Round 3" for Idea https://ideas.intersystems.com/ideas/DPI-I-882
Send and receive WhatsApp messages from InterSystems IRIS Interoperability productions,
through Meta’s official WhatsApp Cloud API.
It provides an outbound adapter and Business Operation to send messages, and an
inbound adapter and Business Service to receive them through Meta’s webhook, plus a
small demo production that echoes back whatever you send it.
Implements the InterSystems idea
DPI-I-882 — Introduce a WhatsApp adapter for IRIS Interoperability.
Your production ──▶ Operation.SendMessage ──▶ Adapter.Outbound ──▶ Meta Cloud API ──▶ phone
│
phone ──▶ Meta webhook ──▶ HTTPS ──▶ /whatsapp (API.Webhook) ──▶ Service.Webhook ──▶ your targets
checks X-Hub-Signature-256
SendTextRequest or SendTemplateRequest to the operation; you getSendResponse with Meta’s message ID./whatsapp/webhook endpoint. Requests without403. Valid messages becomeMessage.Inbound requests sent to the targets you choose.In an Interoperability-enabled namespace:
zpm "install iris-whatsapp-adapter"
Or from a clone of this repository:
zpm "load /path/to/iris-whatsapp-adapter"
Installing creates only the outbound SSL configuration (WhatsApp) and prints the next
steps. It never creates the public webhook endpoint by itself (see step 4 below).
Run these in the namespace where you installed the package. Each command prints nothing
on success; secrets are stored as Interoperability Credentials, never in code.
1. Access token (from Meta, see https://github.com/xJuan21/iris-whatsapp-adapter/blob/master/META-SETUP.md)
Write $System.Status.GetErrorText(##class(WhatsAppMeta.Util.Setup).SetToken(""))
2. Phone Number ID: add a System Default Setting (Interoperability → Configure →
System Default Settings → New) so it survives recompiling the production:
| Field | Value |
|---|---|
| Production Name | WhatsAppMeta.Production.Demo (or your production) |
| Item Name / Host Class Name | WhatsAppMeta.Operation.SendMessage |
| Setting Name | PhoneNumberId |
| Setting Value | your Phone Number ID (not the phone number itself) |
3. Try sending. Start WhatsAppMeta.Production.Demo, then:
Do ##class(WhatsAppMeta.Util.Setup).SendHello("")
You should receive Meta’s hello_world template. Sending works now; steps 4–6 are only
needed to receive messages.
4. Webhook secrets: a verify token you invent, and your Meta App Secret:
Write $System.Status.GetErrorText(##class(WhatsAppMeta.Util.Setup).SetSecrets("",""))
5. Create the webhook endpoint. This creates an unauthenticated web application,
so it shows you exactly what it will change and asks before doing anything:
Write $System.Status.GetErrorText(##class(WhatsAppMeta.Util.Setup).CreateWebApp())
It creates the web application /whatsapp and a role, WhatsAppWebhook, whose resources
are looked up from your namespace’s own databases. Answer y to apply. To undo it, run
RemoveWebApp().
6. Connect Meta to the endpoint: register the webhook URL in Meta, then subscribe your
app to your WhatsApp Business Account:
Write $System.Status.GetErrorText(##class(WhatsAppMeta.Util.Setup).SubscribeApp(""))
Without this last step, Meta’s dashboard Test button works but real messages never
arrive. https://github.com/xJuan21/iris-whatsapp-adapter/blob/master/META-SETUP.md explains why.
Done. Message the number from your phone: the demo production replies Echo: <your text>.
Send: add WhatsAppMeta.Operation.SendMessage to your production and send it either
request:
Set Request = ##class(WhatsAppMeta.Message.SendTextRequest).%New()
Set Request.ToRecipient = "15551234567", Request.Body = "Your order has shipped"
| Request | Use for |
|---|---|
Message.SendTextRequest |
Free-form text. Only allowed within 24 hours of the user’s last message to you |
Message.SendTemplateRequest |
Pre-approved templates (TemplateName, LanguageCode, BodyParameters). Can start a conversation at any time |
Receive: add WhatsAppMeta.Service.Webhook with Pool Size 0 (web requests drive it),
set its adapter’s VerifyTokenCredentials / AppSecretCredentials, and point
TargetConfigNames at your process. It sends one Message.Inbound per message
(FromSender, ContactName, MessageType, Body, MessageId, SentAt).
| Class | Role |
|---|---|
WhatsAppMeta.Adapter.Outbound |
Calls the Graph API; settings PhoneNumberId, ApiVersion (default v26.0), TokenCredentials |
WhatsAppMeta.Operation.SendMessage |
Business Operation for the two send requests |
WhatsAppMeta.Adapter.Inbound |
Verifies the webhook handshake token and X-Hub-Signature-256 |
WhatsAppMeta.API.Webhook |
REST endpoint Meta calls (GET/POST /webhook) |
WhatsAppMeta.Service.Webhook |
Business Service: one Message.Inbound per received message; logs failed delivery statuses as warnings |
WhatsAppMeta.Process.Echo |
Demo process: replies “Echo: …” |
WhatsAppMeta.Production.Demo |
Demo production: webhook → Echo → SendMessage |
WhatsAppMeta.Util.Setup |
SetToken, SetSecrets, CreateWebApp, RemoveWebApp, SubscribeApp, ListSubscribedApps, SendHello |
/whatsapp alone, never the whole web403GET) needs your verify token.WhatsAppWebhook role only. That role needs read access to the database holding%Ens_Credentials, so code running under /whatsapp couldCreateWebApp() warns you beforeOffline unit tests cover the signature and verify-token checks and the outbound payloads:
zpm "test iris-whatsapp-adapter"
To run them from VS Code’s Testing panel instead, set the test root once per namespace:
Set Dir = "/durable/irissys/unittestroot/" Write ##class(%File).CreateDirectoryChain(Dir) Set ^UnitTestRoot = Dir
| Symptom | Cause |
|---|---|
WhatsApp API error 190 |
Access token expired (temporary tokens last 1–2 hours). Store a new one with SetToken |
WhatsApp API error 100 … Object with ID 'messages' |
PhoneNumberId is empty. Set it as a System Default Setting |
131030 Recipient phone number not in allowed list |
On the test number, add the recipient in Meta’s API Setup |
Echo accepted but never delivered; warning 131047 |
Free-form text outside the 24-hour window. Message the number first, or use a template |
| Dashboard Test reaches IRIS, real messages don’t | App not published, or app not subscribed to the WABA (SubscribeApp) |
403 on every webhook call, nothing in the logs |
The web app’s role can’t read the namespace’s databases; re-run CreateWebApp() |
503 from the webhook |
The production isn’t running |
MIT · Privacy policy · Terms
Not affiliated with Meta, WhatsApp, or InterSystems.