---
id: platform/members
title: Workspaces, members, & roles
description: Invite teammates to a Bex workspace, understand role permissions and plan limits, and manage pending invitations and membership.
keywords: [bex, workspace, members, roles, invite, team]
last_updated: 2026-09-23
---

A workspace groups resources and the people who can access them. Signing in to
Bex does not automatically grant access to another person's workspace: an admin
must invite you, and your assigned role determines what you can do.

## Roles and plan limits

| Role | Main permissions |
| --- | --- |
| `viewer` | Read resource details and metrics; no service logs or sensitive values. |
| `contributor` | Viewer access plus logs and operational actions such as restart, suspend, and resume; no general resource creation/deletion or sensitive values. |
| `developer` | Create and delete resources, read sensitive configuration, and manage API keys subject to caller restrictions. |
| `admin` | Resource access plus workspace settings, membership, and billing administration. |
| `billing` | Billing management and non-sensitive resource reads; no service operation or secret access. |

Hobby workspaces are single-member. Pro supports `admin` and `developer`;
Scale and Enterprise also support the other three roles. A plan change cannot
leave members with roles the destination plan disallows. Check current workspace
limits before inviting someone or changing plans.

The API accepts role names case-insensitively and returns uppercase values such
as `DEVELOPER`. OAuth client scopes can restrict access further. See
[API authentication](./api.md) for the distinction between a human session, a
machine key, and an agent's consented credential.

## Invite a teammate

Use the workspace's members settings, or call the API as an authorized admin.
Set `BEX_API_URL` and use an admin user's authorized OAuth access token as
`BEX_TOKEN`, then replace the workspace ID and invitee email. A machine API key
has the developer role and cannot send invitations; see the
[API permission model](./api.md).

```bash
export BEX_WORKSPACE_ID='replace-with-workspace-id'

curl --fail-with-body --silent --show-error \
  -X POST "$BEX_API_URL/v1/workspaces/$BEX_WORKSPACE_ID/members" \
  -H "Authorization: Bearer $BEX_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"email":"teammate@example.com","role":"developer"}'
```

The response describes a pending invitation, including its ID and expiration.
It does not mean the recipient has joined. The recipient signs in or registers
with the matching email and follows the invitation flow. Email verification
requirements depend on installation policy.

Invitation email is best-effort: creating the pending invite can succeed even
if mail delivery fails. Check the address and pending invitations before creating
another. An admin can resend; the replacement link invalidates the old token.

## Manage invitations and membership

Use returned invite IDs and member `subject` values for these routes. The
member identifier is not the person's email address.

| Action | Endpoint |
| --- | --- |
| List members | `GET /v1/workspaces/{workspaceId}/members` |
| List pending invites | `GET /v1/workspaces/{workspaceId}/invites` |
| Resend an invite | `POST /v1/workspaces/{workspaceId}/invites/{inviteId}/resend` |
| Revoke an invite | `DELETE /v1/workspaces/{workspaceId}/invites/{inviteId}` |
| Change a role | `PATCH /v1/workspaces/{workspaceId}/members/{subject}` with `{"role":"viewer"}` on a supporting plan |
| Remove a member | `DELETE /v1/workspaces/{workspaceId}/members/{subject}` |
| Inspect seats | `GET /v1/workspaces/{workspaceId}/seat-usage` |
| Inspect your permissions | `GET /v1/viewer/capabilities?ownerId={workspaceId}` |

Seats count members and outstanding invitations; a returned limit of `0` means
unlimited, not zero available seats. Bex refuses to demote or remove the last
admin. Assign another admin first, then make the intended membership change.

Removing a workspace member is distinct from deleting that person's Bex account.
For offboarding, also review shared credentials and automation in the workspace;
do not assume a membership operation rotates application secrets.

If an operation fails, check your role, OAuth scopes, workspace plan, available
seats, and the returned error. An invitation accepted under the wrong account
must be retried with the intended identity.

See [sign-in and SSO](./sso.md), [environment variables and secrets](./secrets.md),
and [notification preferences](./notifications.md) for related setup.

See [projects and environments](./projects-environments.md) to organize resources within a workspace.

Workspace admins can investigate account and resource operations through
[audit logs](./audit-logs.md).

## Leave a workspace

Remove yourself without involving another admin. In the dashboard, open the
workspace's settings and use the leave action; over the API:

```bash
curl --fail-with-body --silent --show-error \
  -H "Authorization: Bearer $BEX_TOKEN" \
  -X DELETE "$BEX_API_URL/v1/workspaces/$BEX_WORKSPACE_ID/members/me"
```

```graphql
mutation {
  leaveWorkspace(workspaceId: "wks_123")
}
```

The `me` segment (and the argument-free mutation) can only ever name you.
Leaving revokes the keys bound to your membership. Two refusals apply: the
workspace owner cannot leave at all — ownership transfer does not exist yet —
and the last admin cannot leave a workspace nobody could then administer.
Promote another admin first, then leave. Leaving a workspace is not deleting
your account; see [Delete your account](./account-deletion.md).
