---
sidebar_position: 10
title: Workspaces API
description: The /workspaces endpoints — teams with owner, admin and member roles, one billing owner, an audit log — team API keys, key scopes and the account event log.
---

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

# Workspaces API

:::note Behind a flag — lium-platform#208, #123, #124 and #137 are merged; the `/workspaces` endpoints answer `403 Workspaces are not enabled yet.` until a deployment turns `WORKSPACES_ENABLED` on
Until then only `GET /users/me/events` (the whole log, for a signed-in session) and the pre-existing key endpoints answer. The PR numbers on this page say which change each row came from.
:::

What a workspace is, the role matrix, the billing owner and the dashboard are on the renter page, [Workspaces](../pod-users/workspaces.md); this page is the API surface. In lium-platform#208 every `/workspaces` and `/keys` call takes a signed-in session (JWT); `GET /users/me/events` and the pod, executor, volume, template and backup-config routes take `X-API-Key` or a session; lium-platform#123 lets a key read its own workspace (below). The live spec at `https://lium.io/api/openapi.json` carries the request and response schemas once the PR is deployed.

## Which workspace a request acts in

- A **session** (the browser, or the `token` from `POST /users/login` sent as `Authorization: Bearer`) acts in your personal workspace by default. Send `X-Lium-Workspace-Id: <workspace id>` to act in a team you belong to; a workspace you are not a member of answers `403 You are not a member of the workspace in X-Lium-Workspace-Id`, a value that is not a UUID `400`.
- An **API key** acts in the workspace it was created in — a key from before workspaces in its owner's personal one — and never selects another: `X-Lium-Workspace-Id` naming any other workspace answers `403 API key '<name>' acts in its own workspace; do not send X-Lium-Workspace-Id with it` (a header naming the key's own workspace is accepted). To act in a team from a script, create a key in that team.
- A **team key** — a key created in a team workspace, or created in a personal workspace by a member other than the account itself — runs as the team's billing owner (their balance pays). It reaches only the routes that go through the workspace: `/pods`, `/executors`, `/volumes`, `/templates`, `/backup-configs` and `GET /users/me` (which answers with the billing owner's account record). Every other route — SSH keys, registry credentials, payments, the account event log — answers `403 API key '<name>' belongs to the '<workspace>' workspace and reaches only that workspace's pods, volumes, templates and backup configurations …`. In lium-platform#208 every `/workspaces` endpoint takes a session only, so a team key gets `401` there; lium-platform#123 opens the four reads below to a key for its own workspace.
- A team key stops working the moment the member who created it is removed, leaves, or deletes their account: `403 API key '<name>' was created by an account that is no longer a member of its workspace`; a key whose workspace was deleted answers `403 API key '<name>' belongs to a workspace that is gone or that its account has left`. Removing or leaving also deactivates that member's team keys, in the same transaction as the membership change.

## Endpoints

All 13 take a signed-in session (JWT). An API key — personal or team — got `401` on every one of them in lium-platform#208; since lium-platform#123 `GET /workspaces`, `GET /workspaces/{workspace_id}`, `GET /workspaces/{workspace_id}/members` and `GET /workspaces/{workspace_id}/events` also answer a key, for the one workspace the key acts in (`members` and `events` need the `read` scope).

| Method and path | Who may call it | What it does |
|---|---|---|
| `GET /workspaces` | any member | every workspace the caller belongs to, oldest first, with the caller's role in each *(lium-platform#208)* |
| `POST /workspaces` | any account | creates a workspace; the caller becomes its owner and its billing owner *(lium-platform#208)* |
| `GET /workspaces/{workspace_id}` | members | one workspace; a workspace the caller does not belong to answers `404` *(lium-platform#208)* |
| `PATCH /workspaces/{workspace_id}` | owners, admins | rename *(lium-platform#208)* |
| `DELETE /workspaces/{workspace_id}` | owners | soft delete — the workspace disappears from every endpoint; its audit log is kept; `409` while it still has running pods or live volumes *(lium-platform#208)* |
| `GET /workspaces/{workspace_id}/members` | members | the members with their roles; `is_billing_owner` marks whose balance pays *(lium-platform#208)* |
| `POST /workspaces/{workspace_id}/members` | owners, admins | add an existing Lium account by e-mail with a role; admins cannot grant `owner`; `404` when no account has that e-mail, `409` when already a member *(lium-platform#208)* |
| `PATCH /workspaces/{workspace_id}/members/{member_user_id}` | owners, admins | change a role; admins move members between `admin` and `member` and cannot touch owners; the last owner cannot be demoted (`409`) *(lium-platform#208)* |
| `DELETE /workspaces/{workspace_id}/members/{member_user_id}` | owners, admins; anyone for their own id | remove a member, or leave; an owner and the billing owner cannot leave or be removed (`409`) until the role or the billing is handed over; the member's team keys are deactivated *(lium-platform#208)* |
| `POST /workspaces/{workspace_id}/billing-owner/transfer` | the billing owner | hand the paying balance to another member: an owner or admin takes over at once, a plain member has to accept first *(lium-platform#208)* |
| `POST /workspaces/{workspace_id}/billing-owner/accept` | the member named in a pending transfer | take over: their balance pays from now on *(lium-platform#208)* |
| `DELETE /workspaces/{workspace_id}/billing-owner/transfer` | the billing owner or the member asked | withdraw a pending transfer *(lium-platform#208)* |
| `GET /workspaces/{workspace_id}/events` | members | the audit log, newest first: creation, renames, members added / removed / left, role changes, billing-owner transfers and their acceptance or cancellation, deletion — and every pod event made from a workspace request (rents, deletes, stops and restarts, lifecycle changes), since each carries `workspace_id`. Each entry names the user and the session or API key behind it; `since` and `limit` (1–1000, default 200) |

A workspace's response carries `id`, `name`, `role` (the caller's), `billing_owner_user_id`, `pending_billing_owner_user_id` and `created_at`. Invitations by e-mail for people without an account (`/workspaces/{workspace_id}/invitations`, `/workspace-invitations/{token}`) are lium-platform#124; see [Invitations](../pod-users/workspaces.md#invitations).

## The account event log

Today (lium.io, before lium-platform#208) `GET /users/me/events` answers a signed-in session with the account's whole event log, unfiltered and without an actor. With lium-platform#208 it also takes an API key and returns every pod rent request, creation, reboot and deletion with its reason, and every API/SSH key, template and workspace change, each with the session or API key that made it (`actor`; platform-initiated events carry none). Filter with `since`, `pod_id` (a deleted pod still answers) and `api_key_id`; `limit` is 1–1000, default 200. The workspace events above appear here too, on the actor's account.

## Keys and scopes

An API key holds any subset of the scopes `read`, `rent` and `manage` (`scopes` on `POST /keys`); a key created without `scopes` gets all three, as every existing key did. `read` sees every pod of the workspace (without it a key sees only the pods it created); `rent` creates pods; `manage` reboots, edits and deletes pods the key did not create. A key holding `read` alone is refused on every non-GET route (`403 API key '<name>' holds the 'read' scope only …`). Creating, listing and revoking a workspace's keys is for owners and admins (`403 Only workspace owners and admins can manage API keys` for a member); a team key lists in the team, not in its creator's personal workspace. Creating a key while acting in a team (`X-Lium-Workspace-Id` on the session) binds it to that team for good. Details for renters: [API keys](../pod-users/api-keys.md); from the CLI, [`lium keys`](./cli/reference/workspaces.md) (since lium 0.0.43).
