Authentication
Every call to the Wiselook public API carries a bearer token minted from an OAuth2 client that your organisation's admin created on the API clients page.
Client-credentials token (your backend)
Your server-to-server integration uses an OAuth2 client-credentials token:
curl -X POST https://<WISELOOK_HOST>/auth/application/o/token/ \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'client_id=<YOUR_CLIENT_ID>' \
--data-urlencode 'client_secret=<YOUR_CLIENT_SECRET>' \
--data-urlencode 'scope=<space-separated scopes>'
The response contains an access_token (a JWT) and expires_in. Send it
on every API call:
Authorization: Bearer <access_token>
Request only the scopes your client was granted. Requesting a scope the client doesn't hold causes the token request to fail.
Available scopes
Scopes are named <resource>:<verb>. In the portal they're called
permissions: an admin picks them when creating the client on
API clients, and they're fixed for the
life of the client. These are all the scopes a client can be granted:
| Scope | Portal label | Opens |
|---|---|---|
widget_sessions:write | Mint widget visitor sessions | POST /v1/widgets/{id}/sessions (Embed the widget) |
access_codes:write | Create and revoke invite codes | POST /v1/access-codes, DELETE /v1/access-codes/{id} |
access_codes:read | List invite codes and usage | GET /v1/access-codes |
tenant_methodologies:read | List adopted methodologies | GET /v1/adopted-methodologies |
tags:read | List tags (teams, departments, cohorts) | GET /v1/tags |
tenant_users:read | List your organisation's users (memberships, roles, tags) | GET /v1/tenant-users, …/{id}, …/{id}/tags |
tenant_users:write | Update a user's name, role, status and tags | PATCH /v1/tenant-users/{id}, POST …/{id}/tags, DELETE …/{id}/tags/{tag_id} |
evaluations:write | Start an assessment for a member and run its conversation | POST /v1/members/{id}/evaluations, POST …/evaluations/{evaluation_id}/chat/messages |
evaluations:read | Read an assessment and its result | GET /v1/members/{id}/evaluations/{evaluation_id} |
Embedding the widget needs only widget_sessions:write. Once a visitor session is minted, the
widget runs the conversation itself (see
Mint a visitor session).
The Guides walk through each of the other integrations.
Visitor JWT (the widget, in the browser)
Browsers can't safely hold a client secret, so the widget uses a short-lived visitor JWT
instead. Your backend mints one per visitor session by calling the public mint endpoint with
your client-credentials token (scope widget_sessions:write):
curl -X POST https://<WISELOOK_HOST>/v1/widgets/<WIDGET_ID>/sessions \
-H "Authorization: Bearer <CLIENT_CREDENTIALS_TOKEN>" \
-H 'Content-Type: application/json' \
-d '{"external_user_id": "<your-stable-user-id>", "methodology_id": "<METHODOLOGY_UUID>"}'
The response contains the visitor JWT. Hand it to the widget; the widget sends it as its bearer
on the assessment surface (GET /v1/widgets/{id}, /v1/evaluations, /v1/chat/*). The JWT is
Ed25519-signed, expires in about 15 minutes and is bound to the widget's allowed origins, so a
leaked token cannot be replayed from another site.
See Embed the widget for the full flow, including how to re-mint when a session expires mid-conversation.
What your token can access
- Your tenant only. Every token is scoped to your organisation. You cannot read another tenant's data; guessing or supplying another tenant's IDs returns nothing.
- Only your granted scopes. A token can only do what its scopes allow; a call beyond them is rejected.
- The public API surface. Every endpoint documented in this site
(the
/v1/*paths) is available to you with the right token and scope.