Resources
Connecting a shop's WhatsApp
QR-code connect flow, polling, and disconnecting a shop's WhatsApp session.
| Method | Path | Permission | Purpose |
|---|---|---|---|
| GET | /shops/{idOrName}/channels/whatsapp | whatsapp.read | stored channel state + live session |
| POST | /shops/{idOrName}/channels/whatsapp/connect | whatsapp.connect | start connecting; returns a QR or connected |
| GET | /shops/{idOrName}/channels/whatsapp/connect | whatsapp.connect | poll until connected (latest QR each call) |
| POST | /shops/{idOrName}/channels/whatsapp/disconnect | whatsapp.connect | stop the session, keep the configuration |
Flow
POST …/channels/whatsapp/connect
→ { "status": "qr_waiting", "qr": "<raw>",
"qrImageDataUrl": "data:image/png;base64,…",
"expiresAt": "…", "pollAfterMs": 3000, "channelConfigId": "…" }
GET …/channels/whatsapp/connect (every pollAfterMs)
→ { "status": "qr_waiting", … } (the QR rotates every ~20–60s — always show the latest)
→ { "status": "connected", "phone": "24177000000", … }
Other statuses: starting (the bot is booting — poll again) and disconnected (the session dropped — POST connect again). Polling before any POST returns 409 WHATSAPP_NOT_CONFIGURED.
Once connected arrives the API persists exactly what the dashboard's own QR modal does (channel state, the shop's channelStatus.whatsapp, the owner notification number). The WhatsApp session credentials themselves are stored encrypted by the bot the instant the phone scans the code — they never transit this API.
Disconnect
POST …/channels/whatsapp/disconnect stops the live session but keeps the channel's configuration, so a later connect reuses it (and its quota slot) rather than starting over. Returns 404 WHATSAPP_NOT_CONFIGURED if the shop never had a WhatsApp channel at all.