Skip to main content

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:

ScopePortal labelOpens
widget_sessions:writeMint widget visitor sessionsPOST /v1/widgets/{id}/sessions (Embed the widget)
access_codes:writeCreate and revoke invite codesPOST /v1/access-codes, DELETE /v1/access-codes/{id}
access_codes:readList invite codes and usageGET /v1/access-codes
tenant_methodologies:readList adopted methodologiesGET /v1/adopted-methodologies
tags:readList tags (teams, departments, cohorts)GET /v1/tags
tenant_users:readList your organisation's users (memberships, roles, tags)GET /v1/tenant-users, …/{id}, …/{id}/tags
tenant_users:writeUpdate a user's name, role, status and tagsPATCH /v1/tenant-users/{id}, POST …/{id}/tags, DELETE …/{id}/tags/{tag_id}
evaluations:writeStart an assessment for a member and run its conversationPOST /v1/members/{id}/evaluations, POST …/evaluations/{evaluation_id}/chat/messages
evaluations:readRead an assessment and its resultGET /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.