HTTP API: workspaces
The 11 operations tagged workspaces, each with its parameters, its body and what it answers.
List workspaces
GET /v1/workspaces
List the workspaces this caller can reach.
Parameters
order(stringornull, in query): Comma-separated sort fields, '-' reverses.limit(integerornull, in query): How many to return. At least 1; capped at the instance's max_page_size.cursor(stringornull, in query): Continue after a previous page.include_total(boolean, in query): Count the whole result.format(stringornull, in query): 'full' (default), 'compact' for one aligned line per item, or 'ids' for the addresses alone. Compact is roughly a twentieth the size of full.fields(stringornull, in query): Comma-separated field names to return instead of the whole item, e.g. 'ref,title,due_at'. GET /v1/meta lists what each entity has. Cannot be combined with 'format'.
Responses
200:Collection_Workspace_. Successful Response422:HTTPValidationError. Validation Error
Create a workspace
POST /v1/workspaces
Create a workspace, stocked with its vocabulary, owned by you.
Needs instance:workspace_create, which is an instance-tier verb: it happens outside
every workspace, so no role can carry it and only a superuser holds it (§7.1). A token still
narrows it.
Request body: Create as application/json, required.
Responses
201:Workspace. Successful Response422:HTTPValidationError. Validation Error
Read one workspace
GET /v1/workspaces/{id_or_slug}
Return one workspace, by id or by short name.
Parameters
id_or_slug(string, in path, required)format(stringornull, in query): 'full' (default), 'compact' for one aligned line per item, or 'ids' for the addresses alone. Compact is roughly a twentieth the size of full.fields(stringornull, in query): Comma-separated field names to return instead of the whole item, e.g. 'ref,title,due_at'. GET /v1/meta lists what each entity has. Cannot be combined with 'format'.
Responses
200:Workspace. Successful Response422:HTTPValidationError. Validation Error
Change a workspace
PATCH /v1/workspaces/{id_or_slug}
Change a workspace. Omitted fields are untouched; nulls clear (docs/design.md §8.3).
Parameters
id_or_slug(string, in path, required)
Request body: Update as application/json, required.
Responses
200:Workspace. Successful Response422:HTTPValidationError. Validation Error
Move a workspace to the trash
DELETE /v1/workspaces/{id_or_slug}
Soft-delete a workspace. Everything in it leaves the visible world, and returns with it.
Needs workspace:delete, which is the only verb separating the owner and admin
roles — so until this route existed the two were the same role with two descriptions.
The workspace itself is returned rather than a 204, so a caller can see deleted_at and
knows what to hand back to the restore. The last live workspace is refused: an installation
with none cannot file a task and reports itself as interrupted part-way through setup.
Parameters
id_or_slug(string, in path, required)
Responses
200:Workspace. Successful Response422:HTTPValidationError. Validation Error
Who belongs to this workspace
GET /v1/workspaces/{id_or_slug}/members
List this workspace's members and their roles.
Needs workspace:read: knowing who you are working alongside is part of working
somewhere, and it is the question anybody about to add or remove somebody asks first.
Enveloped and unpaginated, like a task's links (§8.4) and for the same reason — a workspace's membership is bounded by how many people somebody put in it.
Parameters
id_or_slug(string, in path, required)format(stringornull, in query): 'full' (default), 'compact' for one aligned line per item, or 'ids' for the addresses alone. Compact is roughly a twentieth the size of full.fields(stringornull, in query): Comma-separated field names to return instead of the whole item, e.g. 'ref,title,due_at'. GET /v1/meta lists what each entity has. Cannot be combined with 'format'.
Responses
200:Collection_Member_. Successful Response422:HTTPValidationError. Validation Error
Add somebody to this workspace
POST /v1/workspaces/{id_or_slug}/members
Give somebody a role in this workspace.
Needs workspace:admin rather than workspace:write: deciding who belongs somewhere is
not the same act as doing work there, and a member who can add members can grant themselves
anything the roles allow. That check did not exist at all at first — the service took an
actor, attributed the event to it, and never asked it anything — and it was found on the
morning this endpoint was written.
Parameters
id_or_slug(string, in path, required)
Request body: Join as application/json, required.
Responses
201:Member. Successful Response422:HTTPValidationError. Validation Error
Change what somebody may do in this workspace
PATCH /v1/workspaces/{id_or_slug}/members/{username}
Move an existing member to another role.
A third verb rather than a flag on the POST, because adding somebody and re-grading them are two acts: one decides that they belong here, the other decides what they may do now that they do. Until this existed the only route was to remove them and add them back, which writes two events for one act and leaves nothing in the record saying a role moved.
Needs user:admin, the same verb that gates adding and removing — its own description is
managing who belongs to this workspace and what they may do here, and this is the half of
that sentence nothing implemented.
Somebody who is not a member is refused by name rather than added, which keeps this and the POST a pair: each turns down the other's case and says which one to run.
The last account able to administer the workspace cannot be moved out of an administering role, for the same reason it cannot be removed — a workspace nobody can administer cannot be repaired from inside, including by granting the role that would repair it.
Parameters
id_or_slug(string, in path, required)username(string, in path, required)
Request body: Regrade as application/json, required.
Responses
200:Member. Successful Response422:HTTPValidationError. Validation Error
Take somebody out of this workspace
DELETE /v1/workspaces/{id_or_slug}/members/{username}
Remove somebody's membership of this workspace.
Here rather than later, for the reason that holds of anything that can be added: somebody joined by mistake can see private projects they should not, and a membership that can only be granted is one whose mistakes are permanent.
The last account able to administer the workspace cannot be removed — a workspace nobody can administer has thrown away the remedy for every later mistake, including that one.
Parameters
id_or_slug(string, in path, required)username(string, in path, required)
Responses
204: Successful Response422:HTTPValidationError. Validation Error
Take a workspace out of the trash
POST /v1/workspaces/{id_or_slug}/restore
Restore a soft-deleted workspace, and everything in it with it.
POST rather than DELETE ?restore=, matching a project's restore, because it is not
a deletion of anything. The short name may have been taken while this was in the trash —
the unique index ignores deleted rows — and that is refused by name with the rename that
clears it, rather than surfacing as a constraint violation.
Parameters
id_or_slug(string, in path, required)
Responses
200:Workspace. Successful Response422:HTTPValidationError. Validation Error
What is in force in this workspace, and where it came from
GET /v1/workspaces/{id_or_slug}/settings
Every setting this workspace may carry, as it applies here.
Each says what is in force, what it would be if nothing stated it, and whether this workspace states it — so a settings page can tell a choice somebody made here from a default nobody chose. A workspace is the widest scope there is, so nothing here is inherited.
Needs workspace:read.
Parameters
id_or_slug(string, in path, required)
Responses
200:SettingsInForce. Successful Response422:HTTPValidationError. Validation Error