Bulk-invite members via the API
Invite tens or hundreds of people into your organisation from your own
backend (an HR system, an onboarding pipeline, a campaign tool) without
clicking through the portal. Each invite is an access code. Whoever
opens its accept link joins your organisation as a member, and the code
can optionally start an assessment for them the moment they join.
Prerequisites
- An API client with these
permissions:
access_codes:writeto create and revoke invite codesaccess_codes:readto list codes and their usagetenant_methodologies:readto list your adopted methodologiestags:readif you group invites (optional)tenant_users:readto reconcile who joined (optional)
- A bearer token minted from that client, as described in
Authentication. The token
carries every permission the client was granted, whichever single
scope you name in the request. The examples below assume it is in
$TOKEN.
Permissions are fixed for the life of a client. If an existing client lacks these, create a new one.
1. Pick a methodology
If each new member should receive an assessment on arrival, the invite must name one of your organisation's adopted methodologies. Any other id is rejected with a 422.
curl "https://$WISELOOK_HOST/v1/adopted-methodologies" \
-H "Authorization: Bearer $TOKEN"
{
"items": [
{
"methodology_id": "009f91ce-…",
"name": "Eric One",
"version": "1.0",
"subscribed_at": "2026-07-27T06:04:24Z"
}
]
}
Use the methodology_id of your chosen methodology as
assessment_methodology_id when creating the invite in step 4.
2. Group the campaign with tags (optional)
Tags are your organisation's own labels (teams, departments, offices, cohorts), defined on the portal's Tags page. Attach them to an invite and everyone who joins through it is tagged on arrival, so a campaign lands pre-grouped for search, reporting and manager scoping.
curl "https://$WISELOOK_HOST/v1/tags" \
-H "Authorization: Bearer $TOKEN"
[
{
"id": "6f2d8a10-…",
"tenant_id": "b4a1c2d3-…",
"type": "department",
"name": "Sales",
"created_at": "2026-08-14T09:12:05Z"
},
{
"id": "9c07e4b2-…",
"tenant_id": "b4a1c2d3-…",
"type": "cohort",
"name": "2026-Q4 onboarding",
"created_at": "2026-09-01T14:30:41Z"
}
]
type is the axis and name the value. Filter one axis with
?type=department. Pass the chosen id values as tag_ids when
creating the invite in step 4. An id that is not yours is rejected with
a 422. Defining new tags stays a portal action.
3. Choose your invite shape
| Shape | How | Good for | Limitation |
|---|---|---|---|
| One multi-use code | one create with max_uses: N | mass campaigns: one link in one email blast | redemptions are anonymous until people join, and a leaked link is usable by anyone until you revoke it or it expires |
| Per-person single-use codes | N creates with max_uses: 1 | tracked rollouts: each code maps to one known invitee | one call and one link per person |
Always set expires_at, and set max_uses explicitly. An unbounded
code with no expiry stays redeemable until you revoke it.
4. Create the invite
One multi-use code for a 50-person sales-team campaign, every joiner tagged into the team and given an assessment on arrival:
curl -X POST "https://$WISELOOK_HOST/v1/access-codes" \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"max_uses": 50,
"expires_at": "2026-10-01T00:00:00Z",
"tag_ids": ["<TAG_UUID>"],
"assessment_methodology_id": "<ADOPTED_METHODOLOGY_UUID>",
"assessment_channel": "text"
}'
{
"id": "3e5f7a90-…",
"tenant_id": "b4a1c2d3-…",
"code": "K7QXM2P9",
"expires_at": "2026-10-01T00:00:00Z",
"max_uses": 50,
"used_count": 0,
"target_role": "member",
"tag_ids": ["6f2d8a10-…"],
"assessment_methodology_id": "009f91ce-…",
"assessment_channel": "text",
"created_by_tenant_user_id": null,
"created_at": "2026-09-11T10:22:37Z",
"updated_at": "2026-09-11T10:22:37Z"
}
The code is what you build the accept link from in step 5; keep the
id if you plan to revoke the invite later (step 7). Notes:
- Everyone who joins through an API-created code gets the
memberrole. Admin and manager invites are portal-only, on purpose. - The assessment spec is both-or-neither:
assessment_methodology_idandassessment_channeltogether, or omit both for a plain invite. - The channel must be enabled for your organisation (422 otherwise).
For per-person codes, loop the same call with "max_uses": 1. Retries
are safe if you send an Idempotency-Key header (any unique string per
logical request; a replay returns the stored response instead of minting
a second code).
5. Distribute the accept link
Build the link from the returned code:
https://$WISELOOK_HOST/tenant-ui/accept?code=<CODE>
Distribution is yours from here. That is the point of this API: Wiselook does not email your invitees. Your backend sends the link through whatever channel your people actually read: the campaign email blast, your corporate messenger (Slack, Teams), an onboarding portal, a QR code on a workshop slide. With per-person single-use codes, each invitee gets their own link, so your system can also track exactly who has and has not acted on it.
Opening the link walks the invitee through single sign-on, creates their Wiselook account if needed, joins them to your organisation and, if the code carries an assessment spec, creates their assessment on the spot.
6. Monitor redemptions
curl "https://$WISELOOK_HOST/v1/access-codes" \
-H "Authorization: Bearer $TOKEN"
[
{
"id": "3e5f7a90-…",
"tenant_id": "b4a1c2d3-…",
"code": "K7QXM2P9",
"expires_at": "2026-10-01T00:00:00Z",
"max_uses": 50,
"used_count": 12,
"target_role": "member",
"tag_ids": ["6f2d8a10-…"],
"assessment_methodology_id": "009f91ce-…",
"assessment_channel": "text",
"created_by_tenant_user_id": null,
"created_at": "2026-09-11T10:22:37Z",
"updated_at": "2026-09-18T08:03:12Z"
}
]
Here 12 of the 50 uses are consumed: 12 people have joined through this code. New members appear on the Members page as they join.
To reconcile exactly who joined (rather than how many), list your
organisation's users through the API. With the tenant_users:read
permission:
curl "https://$WISELOOK_HOST/v1/tenant-users?email=ana@example.com" \
-H "Authorization: Bearer $TOKEN"
A matching row means that address is a member of your organisation; an
empty list means it is not. Without the email filter the same endpoint
lists everyone, with their roles and tags, so your backend can diff the
invitee list against actual joiners.
Two behaviours worth knowing:
- Auto-assessment fires only for new joiners. An already-active member who opens the link again gets no duplicate assessment and consumes no use. (A previously removed member rejoining counts as a new joiner: one use, and the assessment fires.)
- A use is consumed at the moment of a successful join, not when the link is opened.
7. Revoke
curl -X DELETE "https://$WISELOOK_HOST/v1/access-codes/$CODE_ID" \
-H "Authorization: Bearer $TOKEN"
Revoking (or expiry) stops future redemptions immediately; people who already joined are unaffected. Revoking is idempotent. A second delete is a no-op 204.
See also
- API clients for creating the client and choosing its permissions.
- Authentication for token minting in detail.
- Managing members for the portal side of invites, including admin and manager roles.
- Manage members via the API for reading and updating the people who joined (role, status, tags, name).