> ## Documentation Index
> Fetch the complete documentation index at: https://docs.visual-layer.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Workspaces & Organizations

> List workspaces and organizations, view members, and manage workspace roles on self-hosted deployments.

<Note>
  This API is available on self-hosted deployments only. See [Self-Hosting](/docs/self-hosting/setting_up) for setup instructions.
</Note>

<Card title="How This Helps" icon="hand-platter">
  Workspaces organize users and datasets within an organization. Use these endpoints to list workspaces, view membership, check access levels, and change member roles — all programmatically.
</Card>

## Prerequisites

* A self-hosted Visual Layer deployment with authentication enabled.
* An authenticated session with a workspace member account.
* Admin role required for role-change operations.

***

## List Workspaces

Retrieve all workspaces the authenticated user belongs to.

```http theme={"theme":"monokai"}
GET /api/v1/workspaces
```

### Query Parameters

| Parameter         | Type | Required | Description                        |
| ----------------- | ---- | -------- | ---------------------------------- |
| `organization_id` | UUID | No       | Filter workspaces by organization. |

### Example

```bash theme={"theme":"monokai"}
curl "https://<your-vl-domain>/api/v1/workspaces"
```

### Response

```json theme={"theme":"monokai"}
{
  "workspaces": [
    {
      "id": "00000000-0000-0000-0000-000000000001",
      "organization_id": "00000000-0000-0000-0000-000000000001",
      "name": "Default Workspace",
      "created_at": "2026-01-15T10:00:00.000000",
      "updated_at": null,
      "permissions": {
        "can_view": true,
        "can_manage_members": true,
        "can_edit_roles": true,
        "can_create_dataset": true
      }
    }
  ]
}
```

### Workspace Object Fields

<div className="integrations-table">
  | Field             | Type             | Description                                         |
  | ----------------- | ---------------- | --------------------------------------------------- |
  | `id`              | UUID             | Workspace identifier.                               |
  | `organization_id` | UUID             | Parent organization ID.                             |
  | `name`            | string           | Workspace display name.                             |
  | `created_at`      | datetime         | ISO 8601 creation timestamp.                        |
  | `updated_at`      | datetime or null | Last update timestamp.                              |
  | `permissions`     | object or null   | Authenticated user's permissions in this workspace. |
</div>

### Permission Fields

<div className="integrations-table">
  | Field                | Description                                                |
  | -------------------- | ---------------------------------------------------------- |
  | `can_view`           | User can view workspace contents.                          |
  | `can_manage_members` | User can add/remove members and change roles (Admin only). |
  | `can_edit_roles`     | User can modify member roles (Admin only).                 |
  | `can_create_dataset` | User can create new datasets in this workspace.            |
</div>

***

## Get Workspace

Retrieve details for a specific workspace.

```http theme={"theme":"monokai"}
GET /api/v1/workspaces/{workspace_id}
```

### Path Parameters

| Parameter      | Type | Required | Description   |
| -------------- | ---- | -------- | ------------- |
| `workspace_id` | UUID | Yes      | Workspace ID. |

### Example

```bash theme={"theme":"monokai"}
curl "https://<your-vl-domain>/api/v1/workspaces/<workspace_id>"
```

### Response

Returns a single [Workspace object](#workspace-object-fields).

***

## List Workspace Members

Retrieve all members of a workspace with their roles.

```http theme={"theme":"monokai"}
GET /api/v1/workspace/members
```

### Query Parameters

| Parameter      | Type | Required | Description                                             |
| -------------- | ---- | -------- | ------------------------------------------------------- |
| `workspace_id` | UUID | No       | Workspace ID. Defaults to the user's primary workspace. |

### Example

```bash theme={"theme":"monokai"}
curl "https://<your-vl-domain>/api/v1/workspace/members"
```

### Response

```json theme={"theme":"monokai"}
{
  "members": [
    {
      "user_id": "5aadb880-2e5c-445b-a26e-4bc029f1b640",
      "username": "rachel",
      "email": "rachel@visual-layer.com",
      "firstName": "Rachel",
      "lastName": "Cheyfitz",
      "role": "admin",
      "created_at": "2026-01-15T10:00:00.000000"
    },
    {
      "user_id": "b3c4d5e6-7890-abcd-ef01-234567890abc",
      "username": "alex.dev",
      "email": "alex@company.com",
      "firstName": "Alex",
      "lastName": "Developer",
      "role": "editor",
      "created_at": "2026-02-20T14:30:00.000000"
    }
  ],
  "total": 2
}
```

### Member Object Fields

<div className="integrations-table">
  | Field        | Type           | Description                                               |
  | ------------ | -------------- | --------------------------------------------------------- |
  | `user_id`    | UUID           | Visual Layer user ID.                                     |
  | `username`   | string         | Login username.                                           |
  | `email`      | string or null | User email address.                                       |
  | `firstName`  | string or null | First name.                                               |
  | `lastName`   | string or null | Last name.                                                |
  | `role`       | string         | Workspace role: `admin`, `editor`, or `viewer`.           |
  | `created_at` | datetime       | ISO 8601 timestamp of when the user joined the workspace. |
</div>

***

## Update Member Role

Change a workspace member's role. Admin access required.

```http theme={"theme":"monokai"}
PUT /api/v1/workspace/members/{member_user_id}/role
Content-Type: application/json
```

### Path Parameters

| Parameter        | Type | Required | Description                      |
| ---------------- | ---- | -------- | -------------------------------- |
| `member_user_id` | UUID | Yes      | User ID of the member to update. |

### Request Body

| Field          | Type   | Required | Description                                             |
| -------------- | ------ | -------- | ------------------------------------------------------- |
| `role`         | string | Yes      | New role: `admin`, `editor`, or `viewer`.               |
| `workspace_id` | UUID   | No       | Workspace ID. Defaults to the user's primary workspace. |

### Example

```bash theme={"theme":"monokai"}
curl -X PUT \
  -H "Content-Type: application/json" \
  -d '{"role": "editor"}' \
  "https://<your-vl-domain>/api/v1/workspace/members/<member_user_id>/role"
```

### Response

Returns the updated [Member object](#member-object-fields).

### Role Change Behavior

Role changes have cascading effects depending on the transition:

**Promoting to Admin** (single-workspace mode):

* All existing admins are demoted to Editor.
* The promoted user receives Keycloak admin roles.
* All affected users are logged out and must re-authenticate.

**Demoting to Viewer:**

* All dataset-level permissions above Viewer are revoked.
* Datasets owned by the demoted user are transferred to the admin performing the change.
* If the user was an admin, Keycloak admin roles are revoked.

<Note>
  You cannot change your own role. Attempting to do so returns a `400` error.
</Note>

***

## Check Settings Access

Check the authenticated user's access level for workspace settings.

```http theme={"theme":"monokai"}
GET /api/v1/workspace/settings/access
```

### Query Parameters

| Parameter      | Type | Required | Description                                             |
| -------------- | ---- | -------- | ------------------------------------------------------- |
| `workspace_id` | UUID | No       | Workspace ID. Defaults to the user's primary workspace. |

### Example

```bash theme={"theme":"monokai"}
curl "https://<your-vl-domain>/api/v1/workspace/settings/access"
```

### Response

```json theme={"theme":"monokai"}
{
  "can_access": true,
  "can_manage": true,
  "role": "admin"
}
```

| Field        | Description                                                           |
| ------------ | --------------------------------------------------------------------- |
| `can_access` | `true` if the user is a member of the workspace.                      |
| `can_manage` | `true` if the user can manage members and settings (Admin only).      |
| `role`       | User's role in the workspace: `admin`, `editor`, `viewer`, or `null`. |

***

## List Organizations

Retrieve all organizations the authenticated user belongs to.

```http theme={"theme":"monokai"}
GET /api/v1/organizations
```

### Example

```bash theme={"theme":"monokai"}
curl "https://<your-vl-domain>/api/v1/organizations"
```

### Response

```json theme={"theme":"monokai"}
{
  "organizations": [
    {
      "id": "00000000-0000-0000-0000-000000000001",
      "name": "Default Organization",
      "created_at": "2026-01-15T10:00:00.000000",
      "updated_at": null
    }
  ]
}
```

***

## Get Organization

Retrieve details for a specific organization.

```http theme={"theme":"monokai"}
GET /api/v1/organizations/{organization_id}
```

### Path Parameters

| Parameter         | Type | Required | Description      |
| ----------------- | ---- | -------- | ---------------- |
| `organization_id` | UUID | Yes      | Organization ID. |

### Example

```bash theme={"theme":"monokai"}
curl "https://<your-vl-domain>/api/v1/organizations/<organization_id>"
```

### Response

```json theme={"theme":"monokai"}
{
  "id": "00000000-0000-0000-0000-000000000001",
  "name": "Default Organization",
  "created_at": "2026-01-15T10:00:00.000000",
  "updated_at": null
}
```

***

## Python Example

```python theme={"theme":"monokai"}
import requests

VL_BASE_URL = "https://<your-vl-domain>"
session = requests.Session()
# Authenticate via OIDC flow first, then use the session cookie

# List workspaces
resp = session.get(f"{VL_BASE_URL}/api/v1/workspaces")
resp.raise_for_status()
workspaces = resp.json()["workspaces"]
for ws in workspaces:
    manage = "admin" if ws["permissions"]["can_manage_members"] else "member"
    print(f"  {ws['name']} ({manage})")

# List members of default workspace
resp = session.get(f"{VL_BASE_URL}/api/v1/workspace/members")
resp.raise_for_status()
members = resp.json()
print(f"\nWorkspace members: {members['total']}")
for m in members["members"]:
    print(f"  {m['username']} — {m['role']}")

# Promote a member to editor
member_id = members["members"][-1]["user_id"]
resp = session.put(
    f"{VL_BASE_URL}/api/v1/workspace/members/{member_id}/role",
    json={"role": "editor"},
)
resp.raise_for_status()
print(f"\nUpdated {resp.json()['username']} to editor")
```

***

## Response Codes

See [Error Handling](/api-reference/errors) for the error response format.

| HTTP Code | Meaning                                                               |
| --------- | --------------------------------------------------------------------- |
| **200**   | Request successful.                                                   |
| **400**   | Validation error or self-role-change attempt.                         |
| **403**   | Forbidden — user management not enabled, or insufficient permissions. |
| **404**   | Workspace, organization, or member not found.                         |
| **500**   | Internal Server Error — contact support if this persists.             |

***

## Related Resources

<CardGroup cols={2}>
  <Card title="User Management" icon="users" href="/api-reference/user-management">
    Create, update, and delete user accounts on self-hosted deployments.
  </Card>

  <Card title="Admin Settings" icon="blocks" href="/api-reference/admin-settings">
    View and update runtime configuration settings.
  </Card>
</CardGroup>
