17 August 2026
API keys as the default credential, IP allowlists, webhook self-service, Idempotency-Key, and the canonical host.
developers.wasync.app is the canonical host — cloudapi.wasync.app keeps working forever
Improvement.
The developer portal, the docs and the REST API are now documented under
https://developers.wasync.app, and the REST base URL is
https://developers.wasync.app/api/v1.
Nothing you already built has to change.
https://cloudapi.wasync.app/api/v1 is a permanent alias serving exactly the
same API — same keys, same paths, same responses — and it remains valid
indefinitely. This is a documentation change, not a migration: there is no
cut-off date and no deprecation.
The OAuth endpoints, the /.well-known/ discovery documents and the MCP server
URL are protocol identifiers your clients have already registered, so they are
unchanged and still read cloudapi.wasync.app. Keep using them exactly as
issued.
Idempotency-Key on POST /connections — a retried create no longer costs you a second slot
New feature.
Creating a connection provisions a WhatsApp session and consumes a paid slot, so
a client that timed out and retried used to end up with two connections and two
slot charges for one customer. POST /connections now accepts an optional
Idempotency-Key header — the only endpoint that does; omit it and behaviour is
exactly as before.
Within a 24 h TTL: the same key with the same body returns the SAME connection
with 200 and the response header Idempotency-Replayed: true; the same key
with a different body is 400 idempotency_key_reuse; a retry while the first
call is still in flight is 409 idempotency_in_progress with Retry-After: 1;
a key over 255 characters is 400 idempotency_key_invalid. Keys are namespaced
per workspace, and the body comparison is over a canonical hash, so JSON key
order is irrelevant.
Mint one fresh UUID per customer-onboarding attempt — never one per process,
per API key, per day, or a constant, or the second customer you onboard is
handed the first customer's connection. On a replay the qr is re-fetched
fresh, because pairing codes rotate roughly every 20 seconds and a stale one
would not scan.
API keys are the default credential — plus IP allowlists and webhook self-service
New feature.
Authorization: Bearer wsk_live_… now works on every endpoint. Create and
revoke keys at https://developers.wasync.app/keys — the key is shown once and
stored only as a hash, scopes are per key, and scopes plus the reachable
connection list are resolved live on every request.
If you are automating your own account this replaces the entire OAuth flow: no redirect URI, no PKCE, no consent screen, no token refresh. OAuth 2.0 remains, unchanged, for apps that OTHER WASync customers install and consent to. A key can create a workspace's FIRST connection, so the old "make the first one in the portal UI" bootstrap step is gone.
Optional hardening: pin a key to IPv4/IPv6 addresses or CIDR ranges — a call
from an address that is not on the list is refused with 403 ip_not_allowed,
deliberately distinct from 401 invalid_key (unknown or revoked key), because
the fix is to add an address, not to rotate a good key.
New endpoints GET /webhook, PUT /webhook and POST /webhook/rotate let you
point WASync at your endpoint and manage its signing secret without registering
an app: PUT issues the secret, GET never returns it (it reports secretSet
only), and rotation kills the old secret immediately. Nothing changed for
existing OAuth clients, and the webhook signature scheme is unchanged.