Workspace members are the user roster for a specific workspace. A user must already be an org member (tenant_members row) before they can be added to a workspace. The last owner in a workspace cannot be removed until another member is promoted to owner.
Base path: /api/v1/workspaces/:id/members
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /workspaces/{id}/members | List workspace members |
POST | /workspaces/{id}/members | Add an existing org member to the workspace |
PATCH | /workspaces/{id}/members/{user_id} | Update a member’s role |
DELETE | /workspaces/{id}/members/{user_id} | Remove a member |
Roles
| Role | Description |
|---|---|
owner | Full admin including transfer and deletion |
admin | Can manage members and resources |
member | Can create and manage resources |
viewer | Read-only access |
List Members
GET /api/v1/workspaces/{id}/members
Returns all members of the workspace.
Response - 200 OK
{
"data": [
{
"user_id": "usr_abc123",
"email": "alice@example.com",
"name": "Alice",
"avatar_url": null,
"role": "owner",
"joined_at": "2026-05-01T10:00:00Z",
"added_by": null
},
{
"user_id": "usr_def456",
"email": "bob@example.com",
"name": "Bob",
"avatar_url": null,
"role": "member",
"joined_at": "2026-05-10T14:00:00Z",
"added_by": "usr_abc123"
}
]
} Add Member
POST /api/v1/workspaces/{id}/members
Adds an existing org member to the workspace with the given role.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
user_id | UUID | Yes | The user’s ID - must already be a tenant member |
role | string | Yes | owner, admin, member, or viewer |
Response - 201 Created
{
"data": {
"user_id": "usr_def456",
"workspace_id": "ws-uuid",
"role": "member",
"joined_at": "2026-05-22T09:00:00Z",
"added_by": "usr_abc123"
}
} Errors
| Status | Code | Cause |
|---|---|---|
| 422 | NOT_TENANT_MEMBER | User is not a member of the parent org |
| 422 | MISSING_USER_ID | user_id field missing |
| 422 | MISSING_ROLE | role field missing |
| 409 | - | User is already a workspace member |
Update Member Role
PATCH /api/v1/workspaces/{id}/members/{user_id}
Changes a workspace member’s role.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
role | string | Yes | New role: owner, admin, member, or viewer |
Response - 200 OK
Updated workspace member record (same shape as the add response).
Errors
| Status | Code | Cause |
|---|---|---|
| 404 | - | User is not a member of this workspace |
| 422 | MISSING_ROLE | role field missing |
Remove Member
DELETE /api/v1/workspaces/{id}/members/{user_id}
Removes a user from the workspace. This does not remove them from the parent org.
Response - 200 OK
{ "deleted": true } Errors
| Status | Code | Cause |
|---|---|---|
| 404 | - | User is not a member of this workspace |
| 409 | LAST_OWNER | Cannot remove the last workspace owner - promote another member first |
Common Errors
| Status | Code | Cause |
|---|---|---|
| 403 | - | Workspace belongs to a different tenant |
| 404 | - | Workspace or user not found |
| 409 | LAST_OWNER | Refusing to remove the sole workspace owner |
| 422 | NOT_TENANT_MEMBER | User must join the org before joining the workspace |
| 422 | MISSING_USER_ID | user_id body field is required |
| 422 | MISSING_ROLE | role body field is required |
See also
- Workspace Invites API - invite users by email (creates org membership on accept)
- Workspaces API - workspace CRUD
- Error Codes - full error reference