Manage members via the API
Read your organisation's people and manage their tags from your own backend. These are the same people the portal shows on the Members page. Every row combines the platform account (email, display name) with your organisation's view of that person (role, status, tags).
Prerequisites
- An API client with these
permissions:
tenant_users:readto list and read memberstenant_users:writeto update them and change their tags
- A bearer token minted from that client, as described in
Authentication. The examples
below assume it is in
$TOKEN.
1. List and search
curl "https://$WISELOOK_HOST/v1/tenant-users" \
-H "Authorization: Bearer $TOKEN"
{
"items": [
{
"id": "8c1f5d20-3b4e-4a71-9f02-6d5c4b3a2e10",
"email": "maria@example.com",
"name": "Maria Ortega",
"work_email": "m.ortega@acme.com",
"job_title": "Regional Lead",
"preferred_locale": "es-ES",
"role": "member",
"status": "active",
"tags": [{ "id": "1a2b3c4d-…", "type": "team", "name": "Sales EMEA" }],
"joined_at": "2026-09-02T10:11:12Z"
}
],
"total": 38,
"page": 1,
"page_size": 20,
"pages": 2
}
Filters combine (AND): ?email= (exact address match), ?role=,
?status=, ?tag_id=, plus ?page= and ?page_size=. See
Bulk-invite members for using the
email filter to reconcile who joined.
email and name come from the person's platform account. In the rare
case that lookup is momentarily unavailable they come back null; the
rest of the row is always exact.
work_email, job_title and preferred_locale are your organisation's
own record of that person. preferred_locale decides the language an
assessment runs in, before the methodology default applies.
2. Read one member
{id} is the id from the list rows: that person's id within your
organisation. Use it everywhere a member is named, including when
starting an assessment.
curl "https://$WISELOOK_HOST/v1/tenant-users/8c1f5d20-3b4e-4a71-9f02-6d5c4b3a2e10" \
-H "Authorization: Bearer $TOKEN"
The response is a single row in the same shape as the list items. A user who is not a member of your organisation answers 404.
3. Manage a member's tags
Tag membership is a sub-resource with by-value add and remove, so your backend never has to read the current set, modify it, and write the whole thing back (which would lose a concurrent change). Both writes are idempotent. Tag ids come from your organisation's tag list (Tags).
List a member's tags (the same rows the member row embeds):
curl "https://$WISELOOK_HOST/v1/tenant-users/8c1f5d20-3b4e-4a71-9f02-6d5c4b3a2e10/tags" \
-H "Authorization: Bearer $TOKEN"
Add one tag; the response is the updated member row:
curl -X POST "https://$WISELOOK_HOST/v1/tenant-users/8c1f5d20-3b4e-4a71-9f02-6d5c4b3a2e10/tags" \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"tag_id": "1a2b3c4d-5e6f-7a8b-9c0d-e1f2a3b4c5d6"}'
Adding a tag the member already has is a no-op 200. Remove one tag (204; removing a tag the member does not have is also 204):
curl -X DELETE "https://$WISELOOK_HOST/v1/tenant-users/8c1f5d20-3b4e-4a71-9f02-6d5c4b3a2e10/tags/1a2b3c4d-5e6f-7a8b-9c0d-e1f2a3b4c5d6" \
-H "Authorization: Bearer $TOKEN"
A tag id that is not your organisation's answers 422 unknown_tag on
both calls, never a silent success.
4. Update a member
Send only the fields you want to change. Anything you omit is left alone.
curl -X PATCH "https://$WISELOOK_HOST/v1/tenant-users/8c1f5d20-3b4e-4a71-9f02-6d5c4b3a2e10" \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/merge-patch+json' \
-d '{"job_title": "Regional Director", "preferred_locale": "es-ES"}'
The response is the updated member, in the same shape as a read.
| Field | Notes |
|---|---|
name | Their display name |
work_email | Your organisation's email for them, not their login |
job_title | |
preferred_locale | BCP-47. Decides the language an assessment runs in |
role | admin, manager or member |
status | active or removed. invited belongs to the invite flow |
Requires the tenant_users:write permission. Tags are not set here. Use
the add and remove calls above, so adding one tag never rewrites the
rest.
Two behaviours worth knowing:
- Sending
nullis an error, not a way to clear a field. Omit the field instead. An empty document is also rejected, so a no-op PATCH cannot be mistaken for a successful edit. - You cannot demote or remove your last active admin (409
last_active_admin). Promote someone else first.
Errors
| Status | Code | Meaning |
|---|---|---|
| 404 | user_not_found | Not a member of your organisation |
| 422 | unknown_tag | The tag id is not your organisation's (tag add/remove calls) |
| 409 | last_active_admin | Would leave your organisation with no active admin |
| 415 | PATCH sent without Content-Type: application/merge-patch+json | |
| 422 | (validation) | A malformed id or body, a null field, or an empty patch |
See also
- API clients for creating the client and choosing its permissions.
- Authentication for token minting in detail.
- Bulk-invite members for getting people into your organisation in the first place.