Slot quota and connection health
Answers "can I onboard another connection right now?" before you take the order. Everything is scoped to the token's workspace — there is no way to ask about another one. `slots.available` is what `POST /connections` can still consume with an active licence; `slots.nextExpiry` is the date you must renew before, so a slot never expires underneath a customer who already paid. `connections.needsReconnect` counts numbers waiting for their owner to scan a fresh QR (the same state that fires the `connection.disconnected` webhook). **A slot is capacity, not a phone number** and not something you bind to a customer: it attaches when a number actually pairs, and deleting a connection returns its slot to the pool carrying whatever time is left on it, ready for the next number you connect. Map WASync's connection `id` (a stable cuid, echoed by every REST response and by `connection_id` on every webhook) to your own customer record — we mint the id, you map it. Do not try to track slots per customer; track connections.
Answers "can I onboard another connection right now?" before you take the order. Everything is scoped to the token's workspace — there is no way to ask about another one.
slots.available is what POST /connections can still consume with an active licence; slots.nextExpiry is the date you must renew before, so a slot never expires underneath a customer who already paid. connections.needsReconnect counts numbers waiting for their owner to scan a fresh QR (the same state that fires the connection.disconnected webhook).
A slot is capacity, not a phone number and not something you bind to a customer: it attaches when a number actually pairs, and deleting a connection returns its slot to the pool carrying whatever time is left on it, ready for the next number you connect. Map WASync's connection id (a stable cuid, echoed by every REST response and by connection_id on every webhook) to your own customer record — we mint the id, you map it. Do not try to track slots per customer; track connections.
The default way to authenticate. Create a key at https://developers.wasync.app/keys and send it as Authorization: Bearer wsk_live_….
The key is shown once at creation and stored only as a hash — lose it and you revoke it and create another. Each key carries its own scopes (whatsapp.read, whatsapp.send, whatsapp.events, whatsapp.manage) and an optional IP allowlist.
Errors: an unknown or revoked key returns 401 invalid_key; a key whose IP allowlist does not cover the calling address returns 403 ip_not_allowed (a distinct code on purpose — the key is fine, the address is not). Both carry a WWW-Authenticate: Bearer challenge. Scopes and the connection list are resolved live on every request, so revoking a key or narrowing it takes effect on the next call.
In: header
Response Body
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/account"{ "slots": { "total": 10, "used": 7, "available": 3, "nextExpiry": "2026-09-01T00:00:00.000Z" }, "connections": { "total": 7, "connected": 6, "needsReconnect": 1 }}Request a pairing code (link with phone number) POST
Issues a WhatsApp **pairing code** for a connection that is waiting to be paired — the alternative to scanning the QR. The customer opens WhatsApp → Settings → Linked devices → **Link with phone number** and types the 8-character code you return. **Why you want it:** a QR needs two devices — a screen showing the code and a phone photographing it. A large share of real onboardings happen on ONE device: the customer completes your flow on the same phone that runs WhatsApp, and cannot photograph its own screen. For those customers the QR path is not inconvenient, it is impossible. **A pairing code is NOT always available.** The engine can decline to issue one, and that is an ordinary outcome rather than an outage — it answers **502 `pairing_code_unavailable`**. **Your application must keep the QR flow on screen as a fallback.** An integration that offers only the pairing code will strand customers with no way to connect at all. **Re-requestable.** Calling this again on the same connection returns a NEW code and does not rebuild the session, so a "send me another code" button is safe. It is capped: **5 requests per connection per 15 minutes**, then **429 `rate_limited`** with `Retry-After`. The cap is not bureaucracy — repeatedly requesting codes for one number is exactly the pattern WhatsApp's anti-abuse systems act on, and the number at risk is your customer's. **Nothing extra is consumed.** This does not provision anything: the connection, its paid slot and its 7-day trial behave exactly as with QR pairing. The licence is claimed when the number actually pairs, whichever way it paired. **Status monitoring is unchanged.** Poll `GET /connections/{id}` until `status` is `"connected"`, and/or listen for the `connection.connected` webhook. There is no separate "code accepted" event. QR/WAPP connections only (`provider: qr`). Meta/WABA numbers (`provider: cloud_api`) are onboarded through Meta embedded signup and answer 409 `not_supported_for_provider`.
List recent messages GET
Returns recent messages (newest first) scoped to the token's connections. Cursor-paginated.