WASync · Developers

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

GET /connections
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

GET /account
curl https://developers.wasync.app/api/v1/account \
  -H "Authorization: Bearer $WASYNC_API_KEY"
200 response
{
  "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.

POST /connections
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"}'
201 response
{
  "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.

On this page