Agencies and workspaces
An agency that runs WhatsApp for several clients keeps each one in a workspace: a complete account, with its own numbers, contacts, conversations, tags, fields, audiences, suppressions, flows, campaigns, templates, API keys, webhooks and sites. Nothing of one client shows up in another. Every workspace sits on the agency's subscription: one invoice, with numbers, messages, contacts and seats added up across the group.
Workspaces are created and managed in the panel, on the Workspaces screen of the agency's account. The API does not create or delete workspaces; what changes for an integration is below.
How many. The account's owner opens one workspace per WhatsApp number the plan allows, with nobody to ask: a three-number plan covers three clients. On a plan with no cap on numbers, there is no cap on workspaces.
A key belongs to one account
An API key always belongs to one account — the agency's or a client's — and only reaches what is that account's. To integrate a client's site or system, create the key inside the client's workspace (enter the client from the panel's account switcher and go to API keys). A key of the agency's account does not send through a client's numbers, and a client's key does not see the others.
Everything else works as in any account: the key can be limited to some numbers, and the webhooks registered in a workspace only receive that client's events.
Knowing whose account it is
GET /account/me returns parent: the agency that manages and pays for the
account when it is a client's workspace, and null in an ordinary account.
{
"data": {
"id": "cm1clinic",
"name": "Smile Clinic",
"parent": { "id": "cm1agency", "name": "Acme Agency" },
"wabas": []
}
}
Billing each client for what it used
GET /workspaces, with the agency account's key without a number
restriction, returns the group: the agency's account first and then each workspace, with what it
consumed in the billing period (usage: connected numbers, contacts and messages). It is the
figure the agency uses to pass the cost on to each client.
curl https://api.joinotify.com/workspaces \
-H "Authorization: Bearer sk_live_AGENCY_KEY"
A workspace's key gets 409 not_principal, and a key limited to numbers gets 403: a client never
learns about the others.
Reading every client's contacts
GET /contacts?account=all, with the agency's key without a number restriction, lists the contacts
of the agency and of every workspace, with the ordinary list's filters; ?account=<workspace id>
lists one client's. Each contact carries workspace — the client it comes from, or null for the
agency's own.
Handing assets to a client
From the panel, the agency's owner hands what was in the agency's account to a client's workspace: contacts (those the agency still uses are copied; the others change account), a flow (copied as a draft) and an API key. A key handed over keeps the same secret: what the integration sends from then on lands in the client. The key can also be created straight in the workspace, from the agency's account.
Money belongs to the agency
A workspace has no subscription, invoice, wallet or affiliate program of its own. /wallet and
/affiliate answer 409 billed_by_parent with a workspace's key; anything about billing is read
with the agency's key.
Clients that were mixed together
An agency that already served several clients in one account moves each one into its workspace
from the panel, one WABA at a time: the WABA comes with its numbers, templates, conversations,
contacts and the keys limited only to those numbers. After that, those keys belong to the
workspace — the integration keeps working without changing the key, but GET /account/me now
answers with the client and with parent.