On this page
Why this mattersBusiness impactRisk and scopeWhat to sanity-check before this goes live to customersFor Stakeholders
Why this matters
WhatsApp's Business API pricing model is changing for every business on the platform, Dentolize customers included. Without this PR, clinics using the official WhatsApp integration would start being billed by Meta with no visibility into it inside Dentolize, no way to see it coming, and no way to cap it — the first sign of trouble would be an invoice. This PR closes that gap ahead of the change taking effect (1 October), across every surface that sends WhatsApp messages: the web app, the mobile app, scheduled reminders, and the automated bot.
Business impact
- Retention risk mitigated. A clinic blindsided by an unexpected
WhatsApp bill is a churn risk and a support escalation. Visibility and caps reduce both.
- A sales and marketing hook, ready ahead of the actual pricing
change — see For Sales and For Marketing.
- No new permission tier was introduced for the cost data — anyone who
can already see WhatsApp conversations can see what they cost. This is a deliberate simplicity trade-off worth noting: if a future need arises to restrict spend visibility more tightly than conversation visibility, that's not yet supported.
Risk and scope
- Multi-surface consistency risk. The free/paid windowing logic
(conversationWindowEnd / replyWindowOf / conversationIsOpen) is implemented four separate times — once for the server (JS/dayjs), once for the bot service (TypeScript, packages/whatsapp-official), and once each for the web and mobile frontends (JS/moment) — with no shared package. They're kept in sync by matching comments, not by a compiler. A future change to the windowing rules that only updates one copy would silently desync client-shown state from server-enforced billing/limits. See Conversation Windows.
- No backfill for historical messages. Every message sent before this
shipped reports as "Unknown" cost, permanently. This is called out explicitly in the UI (an info tooltip) rather than hidden, but it does mean historical cost reporting from before go-live will never be complete.
- The daily spend cap resets on a rolling window, not a calendar day.
The Redis TTL restarts from whenever the first paid message of a window was sent, not at midnight. For most clinics this is a minor nuance; for ones watching cost closely it's worth knowing precisely what "daily" means here. See Daily Spending Limits.
- The bot's cap fails silently. If
maxBotPaidMessagesis reached, the
bot simply stops auto-replying for the rest of that window with no record surfaced to staff beyond the absence of a reply. A clinic that sets this cap too low could see patients go unanswered without an obvious alert pointing at the cap as the cause (see For Support).
What to sanity-check before this goes live to customers
- Confirm the
1 Octoberdate embedded in the pricing banner
(WHATSAPP_PRICING_DATE in both frontend whatsappUtils.js files) is still accurate closer to release — it's a hardcoded string, not read from configuration.
- Decide whether the bot's silent cap-reached behavior needs a visible
signal to staff (a dashboard flag, a notification) before this ships broadly — right now it's genuinely invisible.