Workspaces and access
Members and invites
Add people to a workspace and manage their roles with a workspace key, a platform key or a signed-in session.
Requires: a role with the Workspace members permissions (Admin by default) in that workspace, or a platform key.
Endpoints
| Method | URL | Input | Does | Auth |
|---|---|---|---|---|
GET | /api/v1/spaces/current/members/ | List members | Key or bearer | |
POST | /api/v1/spaces/current/members/ | {email, role_slug} | Add an existing user | Key or bearer |
PATCH | /api/v1/spaces/current/members/{membership_id}/ | {role_slug} | Change a member's role | Key or bearer |
DELETE | /api/v1/spaces/current/members/{membership_id}/ | Remove a member | Key or bearer | |
POST | /api/v1/spaces/current/invites/ | {email, role_slug} | Add or invite by email | Key or bearer |
GET | /api/v1/spaces/current/invites/ | List invites | Key or bearer | |
DELETE | /api/v1/spaces/current/invites/{invite_id}/ | Revoke an invite | Key or bearer |
role_slug defaults to member. Roles are described in Roles and permissions.
Invite someone
-
Send the invite with the role they should get:
curl -X POST "$CENTRAL_HUB_URL/api/v1/spaces/current/invites/" \ -H "X-API-Key: $ALO_API_KEY" \ -H "X-Space-Slug: $WORKSPACE_SLUG" \ -H "Content-Type: application/json" \ -d '{"email": "ben@acme.com", "role_slug": "editor"}' -
Read the response. A person without an account gets an invite email:
{ "id": null, "added_directly": false, "membership": null, "invite": { "id": 28, "created_by_id": null, "updated_by_id": null, "created_at": "2026-10-13T19:22:20.128528Z", "updated_at": "2026-10-13T19:22:20.128529Z", "space_id": 280, "invited_email": "ben@acme.com", "role_slug": "editor", "token_preview": "sk-Uq.....KsUE", "status": "pending", "expires_at": "2026-10-20T19:22:20.127604Z" } }A person who already has an account is added at once and emailed:
added_directlyistrueandmembershipis set. Custom roles such asanalystexist only in workspaces of an organization. -
Verify:
GET /api/v1/spaces/current/invites/lists the invite aspending.
Invite lifecycle
| Status | Meaning |
|---|---|
pending | Sent and not yet used. Expires after 7 days by default; an expired invite still shows pending, so compare expires_at |
accepted | The person joined the workspace |
revoked | Cancelled with DELETE …/invites/{invite_id}/ |
GET …/invites/returns onlypendinginvites; accepted and revoked invites do not appear.- The invitee accepts with
POST /api/v1/spaces/invites/acceptand{"token": "<token from the invite link>"}, signed in (bearer only); accepting an expired invite returns400This invite has expired.
Change a member's role
-
Find the member's
idwithGET /api/v1/spaces/current/members/. -
Send the new role:
curl -X PATCH "$CENTRAL_HUB_URL/api/v1/spaces/current/members/312/" \ -H "X-API-Key: $ALO_API_KEY" \ -H "X-Space-Slug: $WORKSPACE_SLUG" \ -H "Content-Type: application/json" \ -d '{"role_slug": "editor"}'
Remove a member
- Find the member's
idwithGET /api/v1/spaces/current/members/. - Send
DELETE /api/v1/spaces/current/members/{membership_id}/. The response is204. - The person's API keys for this workspace then get
403User does not have access to the selected space.
Troubleshooting
| Response | Cause | Fix |
|---|---|---|
409 User is already a member of this space | The email already belongs to a member | Change their role instead |
409 OUTSIDE_ORGANIZATION | The person's home organization does not let its members join workspaces outside it, and this workspace is outside it; also on accepting an older invite | Invite them to one of their organization's workspaces, or have its admin set members_can_join_other_organizations |
404 User not found from POST …/members/ | No account has that email | Use POST …/invites/ |
403 You can only assign a role whose permissions you hold | The role grants permissions you do not have | Ask someone with those permissions, or pick a smaller role |
422 Role does not exist in the selected space | The role_slug is not a role in this workspace | List roles with GET /api/v1/spaces/current/roles/ |