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

MethodURLInputDoesAuth
GET/api/v1/spaces/current/members/List membersKey or bearer
POST/api/v1/spaces/current/members/{email, role_slug}Add an existing userKey or bearer
PATCH/api/v1/spaces/current/members/{membership_id}/{role_slug}Change a member's roleKey or bearer
DELETE/api/v1/spaces/current/members/{membership_id}/Remove a memberKey or bearer
POST/api/v1/spaces/current/invites/{email, role_slug}Add or invite by emailKey or bearer
GET/api/v1/spaces/current/invites/List invitesKey or bearer
DELETE/api/v1/spaces/current/invites/{invite_id}/Revoke an inviteKey or bearer

role_slug defaults to member. Roles are described in Roles and permissions.

Invite someone

  1. 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"}'
  2. 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_directly is true and membership is set. Custom roles such as analyst exist only in workspaces of an organization.

  3. Verify: GET /api/v1/spaces/current/invites/ lists the invite as pending.

Invite lifecycle

StatusMeaning
pendingSent and not yet used. Expires after 7 days by default; an expired invite still shows pending, so compare expires_at
acceptedThe person joined the workspace
revokedCancelled with DELETE …/invites/{invite_id}/
  • GET …/invites/ returns only pending invites; accepted and revoked invites do not appear.
  • The invitee accepts with POST /api/v1/spaces/invites/accept and {"token": "<token from the invite link>"}, signed in (bearer only); accepting an expired invite returns 400 This invite has expired.

Change a member's role

  1. Find the member's id with GET /api/v1/spaces/current/members/.

  2. 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

  1. Find the member's id with GET /api/v1/spaces/current/members/.
  2. Send DELETE /api/v1/spaces/current/members/{membership_id}/. The response is 204.
  3. The person's API keys for this workspace then get 403 User does not have access to the selected space.

Troubleshooting

ResponseCauseFix
409 User is already a member of this spaceThe email already belongs to a memberChange their role instead
409 OUTSIDE_ORGANIZATIONThe person's home organization does not let its members join workspaces outside it, and this workspace is outside it; also on accepting an older inviteInvite 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 emailUse POST …/invites/
403 You can only assign a role whose permissions you holdThe role grants permissions you do not haveAsk someone with those permissions, or pick a smaller role
422 Role does not exist in the selected spaceThe role_slug is not a role in this workspaceList roles with GET /api/v1/spaces/current/roles/

On this page