Authentication
Every request carries a bearer token created in your workspace. Tokens belong to one workspace and can only see its data.
Create a token
In the app open Settings, then API and webhooks, and create a key. Choose only the scopes the integration needs. The token starts with wak_ and is shown once; we store only a hash, so a lost token must be replaced. Revoke a key at any time and it stops working immediately.
When a token stops working
A token is tied to the person who created it and to their workspace. It is refused with 401 when any of these is true. For the first three the key is also revoked for good:
- the person who created it is removed from the workspace, or leaves it;
- that person's account is disabled or erased;
- the token is revoked in the app;
- the workspace is closed or deleted (the key is refused; its record is removed when the workspace's data is erased).
Revocation is permanent. If the person is invited back or their account is enabled again, create a new token; the old one stays dead. While a workspace is suspended its tokens answer 403 with a message saying so, and work again when the workspace is reinstated. Changing a member's role does not affect their tokens: a token never has more than agent-level access plus its own scopes.
Send it
Authorization: Bearer wak_your_tokenCookies are ignored on this API. A missing, malformed or revoked token answers 401.
Scopes
A token that holds none of the scopes an endpoint accepts answers 403 and the message names them, for example "This API key needs one of these scopes: messages:write, conversations:write." Some scopes include others: a write scope also allows the matching reads. Available scopes: messages:write, contacts:read, contacts:write, templates:read, conversations:read, conversations:write, broadcasts:read, webhooks:manage.
Good to know: a key with conversations:write can also send free-form session text inside the 24-hour window, because replying is part of managing a chat. Keys created before this was added keep working the same way, so review the keys you hand to other systems and create a new one with only the scopes it needs. Template sends always need messages:write.
| Endpoint | Accepted scopes |
|---|---|
| GET /contacts | contacts:read, contacts:write |
| GET /contacts/count | contacts:read, contacts:write |
| GET /contacts/{target} | contacts:read, contacts:write |
| POST /contacts | contacts:write |
| PUT /contacts/{target} | contacts:write |
| DELETE /contacts/{target} | contacts:write |
| POST /contacts/{target}/tags | contacts:write |
| DELETE /contacts/{target}/tags/{tag} | contacts:write |
| PUT /contacts/{target}/attributes | contacts:write |
| GET /conversations | conversations:read, conversations:write |
| GET /conversations/{target} | conversations:read, conversations:write |
| GET /conversations/{target}/messages | conversations:read, conversations:write |
| POST /conversations/{target}/messages/text | messages:write, conversations:write |
| PUT /conversations/{target}/status | conversations:write |
| PUT /conversations/{target}/assignee | conversations:write |
| POST /conversations/{target}/tags | conversations:write |
| DELETE /conversations/{target}/tags/{tag} | conversations:write |
| GET /messageTemplates | templates:read, messages:write |
| GET /messageTemplates/{id} | templates:read, messages:write |
| POST /messageTemplates/send | messages:write |
| GET /broadcasts | broadcasts:read |
| GET /broadcasts/{id} | broadcasts:read |
| GET /broadcasts/{id}/recipients | broadcasts:read |
| GET /webhooks/event-types | webhooks:manage |
| GET /webhooks | webhooks:manage |
| POST /webhooks | webhooks:manage |
| GET /webhooks/{id} | webhooks:manage |
| PUT /webhooks/{id} | webhooks:manage |
| DELETE /webhooks/{id} | webhooks:manage |
| POST /webhooks/{id}/test | webhooks:manage |
Writes and billing
Write requests are refused with 402 when the trial or subscription has ended, and with 403 while the workspace is suspended. Reads keep working.