# Workspaces

A workspace holds a company's products, environments, planning, test runs and secrets, and the people who work on them. Every other resource belongs to one workspace, named in paths by its slug or ID.

## The Workspace object

A workspace you belong to, with your role in it.

### Attributes

- `id` (string, required): Unique ID of the workspace.
- `name` (string, required): The workspace's display name.
- `slug` (string, required): The workspace's URL name: 2 to 48 lowercase letters, digits and hyphens, such as acme.
- `iconUrl` (nullable string, required): URL of the workspace's icon image, or null.
- `role` (string, one of: `owner`, `admin`, `member`, `viewer`, required): Your role in the workspace: owner, admin, member or viewer.

### Example

```json
{
  "id": "Wk7Qm2RtXa9L",
  "name": "Acme",
  "slug": "acme",
  "iconUrl": "https://images.clankertest.com/workspaces/Wk7Qm2RtXa9L/icon-Ic5TfR2mWq8Z.png",
  "role": "owner"
}
```

## List workspaces

`GET /v1/workspaces`

Returns the workspaces you are an active member of, with your role in each. An account API key sees only its own workspace.

### Returns

Returns an array of [Workspace](https://docs.qa.clankership.net/api/workspaces/object.md) objects. The status is 200.

### Request

```bash
curl https://api.qa.clankership.net/v1/workspaces \
  -H "Authorization: Bearer $CLANKER_API_KEY"
```

### Response

```json
[
  {
    "id": "Wk7Qm2RtXa9L",
    "name": "Acme",
    "slug": "acme",
    "iconUrl": "https://images.clankertest.com/workspaces/Wk7Qm2RtXa9L/icon-Ic5TfR2mWq8Z.png",
    "role": "owner"
  }
]
```

### Errors

- `400` `InvalidInput`: The request is malformed, or a value is not allowed.
- `401` `Unauthorized`: The request has no valid API key.
- `403` `Forbidden`: The key's user or role may not do this.
- `404` `NotFound`: The workspace or object does not exist, or the caller cannot see it.
- `409` `Conflict`: The change conflicts with current data, such as a slug that is already in use.
- `500` `Internal`: Clanker Ship failed to handle the request. Retry, or report the response's x-request-id.

## Create a workspace

`POST /v1/workspaces`

Creates a workspace with you as its owner, plus the default ticket statuses and tags. Fails with Conflict when another workspace uses the slug. Account API keys cannot create workspaces.

### Parameters

- `name` (string, required): The workspace's display name. Surrounding spaces are removed.
- `slug` (string, required): The workspace's URL name: 2 to 48 lowercase letters, digits and hyphens, such as acme. It is trimmed and lowercased, and must be unused.

### Returns

Returns an object with these fields. The status is 200.

- `ok` (boolean, required): Always true: the workspace was created. Always `true`.
- `workspace` (object, required): The new workspace.
  - `id` (string, required): Unique ID of the workspace.
  - `name` (string, required): The workspace's display name.
  - `slug` (string, required): The workspace's URL name: 2 to 48 lowercase letters, digits and hyphens, such as acme.
  - `creatorUserId` (string, required): Your user ID. You are the workspace's first owner.

### Request

```bash
curl -X POST https://api.qa.clankership.net/v1/workspaces \
  -H "Authorization: Bearer $CLANKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme",
    "slug": "acme"
  }'
```

### Response

```json
{
  "ok": true,
  "workspace": {
    "id": "Wk7Qm2RtXa9L",
    "name": "Acme",
    "slug": "acme",
    "creatorUserId": "Us3NfP8kLq2V"
  }
}
```

### Errors

- `400` `InvalidInput`: The request is malformed, or a value is not allowed.
- `401` `Unauthorized`: The request has no valid API key.
- `403` `Forbidden`: The key's user or role may not do this.
- `404` `NotFound`: The workspace or object does not exist, or the caller cannot see it.
- `409` `Conflict`: The change conflicts with current data, such as a slug that is already in use.
- `500` `Internal`: Clanker Ship failed to handle the request. Retry, or report the response's x-request-id.

## Check a workspace slug

`GET /v1/slugs/{slug}`

Tells whether any workspace uses the slug, ignoring case. It does not check that the slug is well formed.

### Parameters

- `slug` (string, in path, required): The slug to check, such as acme.
- `excludeWorkspaceId` (string, in query): A workspace ID, such as Wk7Qm2RtXa9L, whose own slug counts as free.

### Returns

Returns an object with these fields. The status is 200.

- `available` (boolean, required): Whether the slug is free to use.

### Request

```bash
curl https://api.qa.clankership.net/v1/slugs/{slug} \
  -H "Authorization: Bearer $CLANKER_API_KEY"
```

### Response

```json
{
  "available": true
}
```

### Errors

- `400` `InvalidInput`: The request is malformed, or a value is not allowed.
- `401` `Unauthorized`: The request has no valid API key.
- `403` `Forbidden`: The key's user or role may not do this.
- `404` `NotFound`: The workspace or object does not exist, or the caller cannot see it.
- `409` `Conflict`: The change conflicts with current data, such as a slug that is already in use.
- `500` `Internal`: Clanker Ship failed to handle the request. Retry, or report the response's x-request-id.

## Get a workspace

`GET /v1/workspaces/{slug}`

Returns the workspace with its allowed domains and your role in it. Fails with NotFound unless you are an active member, or the account API key belongs to the workspace.

### Parameters

- `slug` (string, in path, required): The workspace's slug or ID, such as acme.

### Returns

Returns an object with these fields. The status is 200. A workspace with its settings, and who is calling: your user ID or account API key and your role.

- `workspaceId` (string, required): Unique ID of the workspace.
- `name` (string, required): The workspace's display name.
- `slug` (string, required): The workspace's URL name: 2 to 48 lowercase letters, digits and hyphens, such as acme.
- `iconUrl` (nullable string, required): URL of the workspace's icon image, or null.
- `allowedDomains` (array of strings, required): Email domains, such as acme.dev, whose people join the workspace as members automatically. Invites must use one of them. Empty allows any address.
- `role` (string, one of: `owner`, `admin`, `member`, `viewer`, required): Your role in the workspace: owner, admin, member or viewer.
- `userId` (nullable string, required): Your user ID, or null when an account API key is calling.
- `accountApiKeyId` (string): The account API key's ID. Present only when an account API key is calling.

### Request

```bash
curl https://api.qa.clankership.net/v1/workspaces/{slug} \
  -H "Authorization: Bearer $CLANKER_API_KEY"
```

### Response

```json
{
  "workspaceId": "Wk7Qm2RtXa9L",
  "name": "Acme",
  "slug": "acme",
  "iconUrl": "https://images.clankertest.com/workspaces/Wk7Qm2RtXa9L/icon-Ic5TfR2mWq8Z.png",
  "allowedDomains": [
    "acme.dev"
  ],
  "role": "owner",
  "userId": "Us3NfP8kLq2V"
}
```

### Errors

- `400` `InvalidInput`: The request is malformed, or a value is not allowed.
- `401` `Unauthorized`: The request has no valid API key.
- `403` `Forbidden`: The key's user or role may not do this.
- `404` `NotFound`: The workspace or object does not exist, or the caller cannot see it.
- `409` `Conflict`: The change conflicts with current data, such as a slug that is already in use.
- `500` `Internal`: Clanker Ship failed to handle the request. Retry, or report the response's x-request-id.

## Update a workspace

`PATCH /v1/workspaces/{slug}`

Sets the workspace's name, slug and allowed domains, and records a `workspace.updated` event. Send `name` and `slug` every time. Only owners and admins can update a workspace.

### Parameters

- `slug` (string, in path, required): The workspace's slug or ID, such as acme.
- `name` (string, required): The workspace's display name. Surrounding spaces are removed.
- `slug` (string, required): The workspace's URL name: 2 to 48 lowercase letters, digits and hyphens. It is trimmed and lowercased, and no other workspace may use it.
- `allowedDomains` (string): Email domains separated by commas, spaces or semicolons, such as acme.dev, acme.com. Leaving it out or sending an empty string clears the list.

### Returns

Returns an object with these fields. The status is 200.

- `ok` (boolean, required): Always true: the change was made. Always `true`.

### Request

```bash
curl -X PATCH https://api.qa.clankership.net/v1/workspaces/{slug} \
  -H "Authorization: Bearer $CLANKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme",
    "slug": "acme",
    "allowedDomains": "acme.dev"
  }'
```

### Response

```json
{
  "ok": true
}
```

### Errors

- `400` `InvalidInput`: The request is malformed, or a value is not allowed.
- `401` `Unauthorized`: The request has no valid API key.
- `403` `Forbidden`: The key's user or role may not do this.
- `404` `NotFound`: The workspace or object does not exist, or the caller cannot see it.
- `409` `Conflict`: The change conflicts with current data, such as a slug that is already in use.
- `500` `Internal`: Clanker Ship failed to handle the request. Retry, or report the response's x-request-id.

## Check a new slug for a workspace

`GET /v1/workspaces/{slug}/slug-availability`

Tells whether the workspace could change to the slug in `newSlug`, ignoring case. The workspace's own slug counts as free. Any member can check.

### Parameters

- `slug` (string, in path, required): The workspace's slug or ID, such as acme.
- `newSlug` (string, in query, required): The slug to check, such as acme-labs.

### Returns

Returns an object with these fields. The status is 200.

- `available` (boolean, required): Whether the slug is free to use.

### Request

```bash
curl "https://api.qa.clankership.net/v1/workspaces/{slug}/slug-availability?newSlug=acme-labs" \
  -H "Authorization: Bearer $CLANKER_API_KEY"
```

### Response

```json
{
  "available": true
}
```

### Errors

- `400` `InvalidInput`: The request is malformed, or a value is not allowed.
- `401` `Unauthorized`: The request has no valid API key.
- `403` `Forbidden`: The key's user or role may not do this.
- `404` `NotFound`: The workspace or object does not exist, or the caller cannot see it.
- `409` `Conflict`: The change conflicts with current data, such as a slug that is already in use.
- `500` `Internal`: Clanker Ship failed to handle the request. Retry, or report the response's x-request-id.

## Upload a workspace icon

`POST /v1/workspaces/{slug}/icon`

Replaces the workspace's icon with a PNG, JPEG or WebP image under 256 KB, and records a `workspace.icon_updated` event. Only owners and admins can change the icon.

### Parameters

- `slug` (string, in path, required): The workspace's slug or ID, such as acme.
- `icon` (file, required): A PNG, JPEG or WebP image under 256 KB for the workspace icon.

### Returns

Returns an object with these fields. The status is 200.

- `ok` (boolean, required): Always true: the icon was replaced. Always `true`.
- `iconUrl` (string, required): URL of the new icon image.

### Request

```bash
curl -X POST https://api.qa.clankership.net/v1/workspaces/{slug}/icon \
  -H "Authorization: Bearer $CLANKER_API_KEY" \
  -F "icon=@icon.png"
```

### Response

```json
{
  "ok": true,
  "iconUrl": "https://images.clankertest.com/workspaces/Wk7Qm2RtXa9L/icon-Ic5TfR2mWq8Z.png"
}
```

### Errors

- `400` `InvalidInput`: The request is malformed, or a value is not allowed.
- `401` `Unauthorized`: The request has no valid API key.
- `403` `Forbidden`: The key's user or role may not do this.
- `404` `NotFound`: The workspace or object does not exist, or the caller cannot see it.
- `409` `Conflict`: The change conflicts with current data, such as a slug that is already in use.
- `500` `Internal`: Clanker Ship failed to handle the request. Retry, or report the response's x-request-id.

## List seeded workspaces

`GET /v1/workspaces/{slug}/seeds`

Returns the seeded local development workspace when this database has it, and whether you have joined it. You must belong to the workspace in the path; it does not filter the results.

### Parameters

- `slug` (string, in path, required): The workspace's slug or ID, such as acme.

### Returns

Returns an array of objects with these fields. The status is 200. The seeded workspace, or nothing when this database does not have it.

- `id` (string, required): Unique ID of the seeded workspace.
- `name` (string, required): The workspace's display name.
- `slug` (string, required): The workspace's URL name: 2 to 48 lowercase letters, digits and hyphens, such as acme.
- `description` (string, required): What the seeded workspace is for.
- `joined` (boolean, required): Whether you are an active member of it.

### Request

```bash
curl https://api.qa.clankership.net/v1/workspaces/{slug}/seeds \
  -H "Authorization: Bearer $CLANKER_API_KEY"
```

### Response

```json
[
  {
    "id": "localClanker",
    "name": "Clanker Ship",
    "slug": "clanker-ship",
    "description": "Clanker Ship's own products and environments, with sample teams, projects and tickets.",
    "joined": false
  }
]
```

### Errors

- `400` `InvalidInput`: The request is malformed, or a value is not allowed.
- `401` `Unauthorized`: The request has no valid API key.
- `403` `Forbidden`: The key's user or role may not do this.
- `404` `NotFound`: The workspace or object does not exist, or the caller cannot see it.
- `409` `Conflict`: The change conflicts with current data, such as a slug that is already in use.
- `500` `Internal`: Clanker Ship failed to handle the request. Retry, or report the response's x-request-id.

## Join a seeded workspace

`POST /v1/seeds/{workspaceId}/join`

Makes you an owner of a seeded local development workspace. Fails with InvalidInput when the ID is not a seeded workspace or the workspace is missing from this database.

### Parameters

- `workspaceId` (string, in path, required): The seeded workspace's ID, such as localClanker.

### Returns

Returns an object with these fields. The status is 200.

- `ok` (boolean, required): Always true: you joined. Always `true`.
- `slug` (string, required): The seeded workspace's slug, such as clanker-ship.

### Request

```bash
curl -X POST https://api.qa.clankership.net/v1/seeds/{workspaceId}/join \
  -H "Authorization: Bearer $CLANKER_API_KEY"
```

### Response

```json
{
  "ok": true,
  "slug": "clanker-ship"
}
```

### Errors

- `400` `InvalidInput`: The request is malformed, or a value is not allowed.
- `401` `Unauthorized`: The request has no valid API key.
- `403` `Forbidden`: The key's user or role may not do this.
- `404` `NotFound`: The workspace or object does not exist, or the caller cannot see it.
- `409` `Conflict`: The change conflicts with current data, such as a slug that is already in use.
- `500` `Internal`: Clanker Ship failed to handle the request. Retry, or report the response's x-request-id.
