Best Practices
Messaging — Best Practices
The recommended way to build a fast, correct inbox.
✓ Treat sending as async
The send endpoint returns before delivery. Render optimistically with a front_id,
then confirm on the message-ack WebSocket event. Don't block the UI on the HTTP
response.
✓ Reconcile on front_id
Pass a client-generated front_id on every send. Both the HTTP response and the
message WS event echo it — use it to replace your optimistic bubble instead of
appending a duplicate.
✓ Use realtime, not polling
Subscribe to /messaging/events for new messages, receipts, and presence. Polling
GET /messages wastes requests and lags. Fall back to a refetch only on reconnect.
✓ Paginate everything
GET /chats/all and GET /messages/:chatSlug take page / limit. Load older
messages on scroll-up; never fetch a whole conversation at once.
✓ Respect the permission level in the UI
Read chat_rights[] and hide send/edit/delete when the level is D. The backend
enforces it anyway (403), but hiding the action is better UX than a failed click.
✓ Verify webhook signatures
If you consume provider webhooks, always verify the signature
(x-webhook-hmac, x-hub-signature-256, tiktok-signature) before trusting the
body. Never disable verification in production.
✓ Check the session is connected
Before a send campaign, confirm the session status is connected. Listen for
session.status.updated and surface a reconnect prompt (QR for WAHA) when it drops.
✓ Mind provider limits
- Only WAHA supports edit/delete and group chats.
- WhatsApp Cloud enforces the 24-hour customer-service window — use an approved template to reopen a conversation.
- Media caption applies to the first file only.
✗ Don't bypass the access services
For any new query, filter chats through ChatVisibilityPolicy /
ChatAccessFilterBuilder. Don't hand-roll visibility SQL — it will leak chats
across roles. See Backend Integration.