Skip to main content
The qr mode of POST /v1/channels/whatsapp/connect pairs a channel without Embedded Signup: the client receives a QR, scans it with WhatsApp mobile (Settings -> Linked Devices -> Link a device) and when pairing completes receives the channel_id of the newly created channel. No browser step, no official WABA, no Cloud API. The integration uses WhatsApp multi-device under the hood. This is what keebai whatsapp connect --qr does in the CLI.

General flow

1

Your backend starts the session

POST /v1/channels/whatsapp/connect with mode: "qr". Returns session_id + stream_url (relative SSE path).
2

Subscribe to the SSE stream

GET {stream_url} with Accept: text/event-stream and Authorization: Bearer <PAT>. You’ll receive real-time events: qr, connecting, connected, failed, disconnected.
3

Show the QR to the user

Each qr event carries a string payload. Render it as a QR (in the terminal with qrcode-terminal, on web with qrcode, etc.). If the code expires before it’s scanned, a new qr arrives automatically.
4

Receive the created channel

Once scanned successfully, the stream closes with a connected event whose data includes channel_id, phone_number and push_name.

Start a QR session

POST /v1/channels/whatsapp/connect Required scope: channels:connect

Request

pipeline_id and coexistence_enabled don’t apply to QR mode. If you send them, the API responds 400 QR_MODE_CANNOT_USE_COEXISTENCE_OR_PIPELINE.

Response 201

SSE event stream

GET /v1/channels/whatsapp/connect/:session_id/qr-stream Required scope: channels:connect Headers: Accept: text/event-stream, Authorization: Bearer kbai_pk_xxx.

Events

When connected, failed or disconnected arrives, the stream closes. The client should close the connection too.

curl example

Rendering the QR

In a terminal with qrcode-terminal (Node):
On the web, with qrcode:

CLI equivalent

The CLI creates the session, opens the stream, draws the QR in the terminal, refreshes it automatically, and on scan prints Channel ch_xxx connected (phone +56…, as Juan).

Troubleshooting

Expired QR

Pairing emits fresh QRs automatically every ~20 seconds. Don’t restart the session: just wait for the next qr event.

4 linked-device limit

WhatsApp allows up to 4 devices per account. If the session ends with failed mentioning device limit, free a slot on the mobile (Settings -> Linked Devices) and call POST /v1/channels/whatsapp/connect again.

Expired session (5 min)

If nobody scanned, the stream closes and the session_id stops working. Request a new session.

Don't use Cloud API against this channel

QR channels don’t support templates or bulk sends (Meta doesn’t expose Cloud API on multi-device). A template message on channel: "whatsapp_qr" is rejected with 422 MESSAGE_TYPE_NOT_SUPPORTED_FOR_CHANNEL, and POST /v1/messages/bulk returns 400 QR_NOT_SUPPORTED_FOR_TEMPLATE_OR_BULK. Text and media work as usual.

Sending messages

Once connected, QR channels show up in GET /v1/whatsapp/numbers with connection_type: "qr" and are used with the same endpoint as Cloud API ones: