
The Chatwoot page — connection status, mirroring toggle, inbox/account IDs, reconnect, and credential update.
Prerequisite: FRONTEND_URL (self-hosted Chatwoot)
If you run a self-hosted Chatwoot, its FRONTEND_URL environment variable must be set before connecting:
- Use the exact public URL (same scheme/host as the browser), no trailing slash, reachable from the internet — never
localhostor an internal IP. - Restart both the web and sidekiq containers afterwards (Rails derives
default_url_options[:host]from it at boot).
Missing host to link to! in the logs, the message shows as sent in Pilot Status, and the media arrives on WhatsApp.
Set up the integration
The integration is configured per number on the Chatwoot page of the Pilot Status dashboard.1
Gather three credentials from Chatwoot
- Instance URL — your Chatwoot base URL (e.g.
https://chatwoot.your-domain.comorhttps://app.chatwoot.com). - Account ID — the number in your Chatwoot URL after
/app/accounts/. - User Access Token — from your Chatwoot profile settings.
2
Connect in Pilot Status
Open the Chatwoot page in the dashboard, select the WhatsApp number, and paste the three values. Pilot Status automatically creates the inbox and the webhook in your Chatwoot account — you never paste a webhook URL manually. Unofficial (web/QR) numbers get an API inbox (message mirror); official Meta Cloud numbers get a native
whatsapp_cloud inbox — see the prerequisite below.3
Talk
Inbound WhatsApp messages (including media) open conversations in the new inbox; agent replies flow back to WhatsApp. Message history and delivery status stay in sync.
Channel mode: API mirror vs native Cloud
Every number connects in one of two modes. Pick it in the Channel mode selector on the Chatwoot page (default Automatic):- API mirror (Model A) — Pilot Status mirrors messages and media into a Chatwoot API inbox. Chat only (no native voice). It does not depend on
WHATSAPP_CLOUD_BASE_URL, so it works on a shared Chatwoot. - Native WhatsApp Cloud (Model B) — Chatwoot talks to Meta directly through the Pilot Status layer using a native
whatsapp_cloudinbox. Enables native voice/calling and native messaging (no mirror). Requires a dedicated Chatwoot withWHATSAPP_CLOUD_BASE_URLpointed at the layer (see the warning above). - Automatic (default) — official numbers → native; unofficial numbers → mirror.
Send history to Chatwoot
Coexistence Meta numbers (a WhatsApp Business App migrated onto the platform via Embedded Signup) import ~30 days of chat history on connect. That history shows up in the dashboard /chat view but is not mirrored to Chatwoot automatically. On the Chatwoot page, the Sync history to Chatwoot button replays that already-stored history into the connected inbox.- Both channel modes (coexistence numbers). Works whether Chatwoot is connected as an API mirror (Model A) or a native
whatsapp_cloudinbox (Model B). The native replay is inbound-only — the customer’s incoming history is replayed; the business’s own outbound replies aren’t re-injected (they never appeared in the native inbox anyway) — and is best run in a maintenance window, since it can briefly notify agents as conversations are (re)created. - Order preserved, date in the body. Messages are posted oldest-first. Because Chatwoot stamps every posted message at import time (it does not accept a backdated timestamp), the original date/time is prefixed into each message body —
[dd/mm/yyyy hh:mm], in the tenant’s timezone. - Idempotent. Re-clicking is safe — it only re-posts messages that never landed.
- On finish (API mirror mode), the touched conversations are marked read and resolved so agents aren’t flooded with notifications. Native mode can’t mark-read automatically — run it in a maintenance window.
- Old media whose Meta reference has already expired may import as a
[mídia]placeholder (media bytes are captured to storage at import time, so recent media survives).
POST /v1/chatwoot/history-sync (number-scoped key), or the MCP tools chatwoot_history_replay (start), chatwoot_history_replay_get (progress), and chatwoot_history_replay_cancel.
Pause or disconnect
On the same Chatwoot page you can pause the sync per number (a toggle — nothing is deleted; flip it back to resume) or disconnect the integration entirely.Voice calls
Voice calls and the messaging inbox above are separate surfaces — WhatsApp call events are not posted into the mirrored conversations. There are two ways to work with calls:- Handle calls in the Pilot Status panel (shipped, no setup). The dashboard /chat page has a built-in softphone that answers and places WhatsApp voice calls for both connection types — Official (Meta Cloud API) numbers over WebRTC and unofficial (Pilot Status web) numbers over a server-side audio session. This is the fastest way to take calls right next to your conversations. See Voice Calls.
- Answer calls natively inside Chatwoot (advanced, self-hosted). Chatwoot v4.15+ ships a native voice channel that can be routed through Pilot Status for Meta Cloud API numbers: agents get a ringing call banner in the Chatwoot inbox and talk over WebRTC, while your Meta token stays with Pilot Status. Full validated walkthrough: Chatwoot Voice Calls. Chatwoot Cloud (
app.chatwoot.com) and unofficial numbers are not supported for this path.
Related
- Chatwoot Voice Calls — take WhatsApp calls inside Chatwoot via the Pilot Status Meta layer.
- Live Chat dashboard
- Data Retention & PII Modes — the Chatwoot relay keeps working even in
RELAY_ONLYmode.