Connection types
The provider field is qr or cloud_api. What each one can do, and where the two genuinely differ.
Every connection reports a provider, and it is one of two values:
provider | What it is | How it is onboarded |
|---|---|---|
qr | An ordinary WhatsApp number (sold as WAPP), paired by linking a device. | POST /connections, then scan a QR or type a pairing code. Entirely self-serve through the API — no Meta Business account. |
cloud_api | A WhatsApp Business number (sold as WABA) registered with Meta, on the official Cloud API. | Meta embedded signup, not this API. |
Both types send and receive through the same endpoints, with the same request bodies and the same two message ids. If you assumed QR-from-your-own-app was impossible: it is not.
Where they actually differ
Webhooks. Events fire for qr connections only. cloud_api connections
emit no webhooks today — poll GET /messages and GET /connections/{id} for
those.
Pairing. POST /connections/{id}/pairing-code is a qr concept. A
cloud_api number answers 409 not_supported_for_provider; that is a permanent
refusal, so do not retry it.
Send latency. A qr send normally takes 1–7 s (up to ~20 s for a long text)
and can take ~2.5 minutes on the self-heal path. A cloud_api send is about 1 s.
Size your HTTP timeout for the slow one: at least 180 s.
Marking read. POST /messages/read marks the whole chat on a qr
connection. A cloud_api connection can only mark one specific message, so a
phone-only request resolves your most recent inbound message from that number
automatically.
Volume. A newly paired qr number has 72-hour warm-up caps on hourly volume;
exceeding one returns 429 warmup_limited. See
Licences & trial.
Session health. A qr connection is bound to a phone that has to stay
reachable, so it can drop and be asked to re-pair — that is what
connection.disconnected / connection.connected and the needs_reconnect flag
are for. A cloud_api connection never scans anything and does not have that
failure mode.
Unknown providers do not leak
provider maps to null rather than passing through an unrecognised value. If
a new connection kind is ever added it will be named here deliberately, so
branching on qr / cloud_api today is safe — but treat null as "a kind this
client does not know about" rather than crashing on it.