Your first call
List the connections your key can reach, and check you have capacity before you provision another.
Base URL https://developers.wasync.app/api/v1.
List the connections you may use
curl https://developers.wasync.app/api/v1/connections \
-H "Authorization: Bearer $WASYNC_API_KEY"Only connections with an active licence appear. Each carries a provider of
qr or cloud_api, an id (a cuid — the stable identifier you should store
against your own customer record) and a status. Uses whatsapp.read.
Already calling cloudapi.wasync.app/api/v1? Keep doing it.
developers.wasync.app is the canonical host, but cloudapi.wasync.app is a
permanent alias for exactly the same API — same keys, same paths, same
responses — and it remains valid indefinitely. No existing integration has to
change anything. The OAuth endpoints, the /.well-known/… documents and the MCP
server URL are protocol identifiers registered by clients: they stay on
cloudapi.wasync.app on purpose.
Check your capacity before you promise it
curl https://developers.wasync.app/api/v1/account \
-H "Authorization: Bearer $WASYNC_API_KEY"{
"slots": {
"total": 30,
"used": 28,
"available": 2,
"nextExpiry": "2027-08-08T09:00:00.000Z"
},
"connections": {
"total": 28,
"connected": 27,
"needsReconnect": 1
}
}slots.available tells you whether you can onboard another number right now,
and nextExpiry is the date you need to invoice your own customer before — so a
slot never expires underneath someone who has already paid you.
connections.needsReconnect counts the numbers currently waiting for their owner
to scan a QR; subscribe to connection events to be told
the moment that number changes instead of polling for it. Uses whatsapp.read.
A slot is capacity, not a phone number. Delete a connection and its slot returns to your pool carrying whatever time is left on it — the next number you connect picks it up automatically. That is what lets you move a paid slot from a departing customer to a new one without paying twice.
Connect a number
One call creates the connection and returns a QR code to scan. It works on a brand-new workspace with no connections at all — with a key there is nothing to click in a portal first.
curl -X POST https://developers.wasync.app/api/v1/connections \
-H "Authorization: Bearer $WASYNC_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"label":"Support line"}'{
"connection": {
"id": "conn_8f3a21",
"status": "connecting",
"qr": "data:image/png;base64,iVBORw0KGgo…"
}
}The QR you get here does not stay valid
WhatsApp rotates the pairing code roughly every 20 seconds, so the qr in
the create response is stale within seconds of being displayed. This fails
silently: the phone never pairs and nothing on screen explains why. Poll
GET /connections/{id} every 3–5 s and re-render the qr from every response.
Do not cache it, and do not hide the refresh behind a button the user has to
press. Pairing code & QR covers the one-device
alternative.
Uses whatsapp.manage. Connections created this way are qr numbers;
cloud_api numbers are onboarded through Meta embedded signup instead. This
endpoint is standalone-workspace only — a Bitrix24 portal is answered with
403 forbidden_portal_kind, because there connections are created by the portal
admin inside WASync. Send an Idempotency-Key — creating a connection consumes
a paid slot, and a timed-out retry without one buys you two.
Errors & idempotency has the four cases
you must handle.