WaConnect

Connect WhatsAppConnect a number

Connect a number

Let your users link WhatsApp from inside your app.

To send and receive messages, a WhatsApp number has to be linked to WaConnect — the same way WhatsApp Web is linked: someone opens WhatsApp on the phone and scans a QR code.

With the API, your users can do this inside your own app. There are three ways to show them the QR code, from easiest to most custom.

Inbox or API numbers#

Every number is used one of two ways, never both:

Inbox numberAPI number
Used fromThe WaConnect inbox, by your teamYour own software, through the API
MessagesSaved and shown in the inboxNot saved in WaConnect: sent to your webhooks, and your software keeps its own copy
Photos and documentsKeptKept for about 24 hours, so you can download them
API keys and webhooksCan't use itUse it
CreditsCharged per messageCharged per message, the same

Numbers created with POST /v1/numbers are API numbers. In the dashboard you choose when you connect a number, and you can switch later on the number's page. Switching starts fresh: an inbox number's saved chats are deleted when it becomes an API number.

1. Create the number#

POST /v1/numbers creates a number, starts pairing and returns a connectUrl — a private page that shows the live QR code.

curl https://api.waconnect.ai/v1/numbers \
  -H "Authorization: Bearer wc_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{"label":"Front desk"}'
response.jsonjson
{
  "id": "01a0f44d-c969-75b1-955d-3841d817f711",
  "label": "Front desk",
  "phoneNumber": null,
  "status": "PENDING",
  "mode": "API",
  "connectedAt": null,
  "lastDisconnectedAt": null,
  "createdAt": "2026-10-01T10:00:00.000Z",
  "connectUrl": "https://waconnect.ai/connect/9Ewps…Jr18"
}

The link is private to that number: show it only to the user who is connecting it.

2. Show the QR code#

Put the connectUrl in an iframe inside your modal. Our page shows only the QR code, the instructions and the result — styled to fit any app — and tells your page when the number connects.

<div id="whatsapp-modal" class="modal">
  <iframe
    src="CONNECT_URL_FROM_YOUR_SERVER"
    title="Connect WhatsApp"
    style="width: 400px; height: 600px; border: 0; border-radius: 16px"
  ></iframe>
</div>
 
<script>
  window.addEventListener("message", (event) => {
    if (event.origin !== "https://waconnect.ai") return // only trust WaConnect
 
    if (event.data.type === "waconnect.connected") {
      console.log("Connected:", event.data.phoneNumber)
      closeModal()
    }
    if (event.data.type === "waconnect.link_invalid") {
      // The link was used or replaced: ask your server for a new one.
    }
  })
</script>

Add ?theme=dark to the URL for a dark widget. See the widget reference for every event.

Option B — In a new tab or window#

Open the connectUrl with window.open(...). The same events are sent to your page (via window.opener), so you can close the window when the number connects.

Option C — Draw the QR yourself (white-label)#

Poll GET /v1/numbers/:id/qr every few seconds and render the qr string with any QR library. WaConnect never appears on screen.

GET /v1/numbers/:id/qrjson
{ "status": "CONNECTING", "qr": "2@AbC…", "generatedAt": "2026-10-01T10:00:05.000Z", "expired": false }
  • qr: null, expired: false — a code is on its way, try again in a moment.
  • expired: true — the code timed out; call POST /v1/numbers/:id/connect-link to start a new one.
  • status: "CONNECTED" — done.

3. Know when it's connected#

Any of these tells you:

  • the widget's waconnect.connected browser event (options A and B);
  • the number.connected webhook on your server — the most reliable;
  • GET /v1/numbers/:id returning "status": "CONNECTED".

QR codes expire#

WhatsApp keeps a pairing session open for about a minute. If nobody scans in time, the widget shows Get a new code; in your own UI, call POST /v1/numbers/:id/connect-link, which starts a fresh code and returns a new link (the old one stops working).

A connect link works until it's used (the number connects), replaced by a newer link, or the number is removed. It doesn't expire by time.

Connecting a number needs a positive credit balance; at $0, POST /v1/numbers answers 402 CREDITS_REQUIRED.