# Account API keys

An account API key (`ctk_…`) belongs to one workspace instead of a person, so CI and other automation can call the API. It acts in that workspace with the role it was given. Admins and owners manage account API keys, and only owners manage keys with the owner role.

## The AccountApiKey object

A workspace's API key that acts with a role instead of as a person.

### Attributes

- `id` (string, required): Unique ID of the account API key.
- `name` (string, required): The key's name, such as Release CI.
- `role` (string, one of: `owner`, `admin`, `member`, `viewer`, required): The workspace role the key acts with.
- `lastFour` (string, required): The key's last four characters, to tell keys apart.
- `createdAt` (string, required): When the key was created, as an ISO 8601 timestamp.

### Example

```json
{
  "id": "Ak2WqH9sDf5T",
  "name": "Release CI",
  "role": "member",
  "lastFour": "cZaE",
  "createdAt": "2026-10-01T16:20:00.000Z"
}
```

## List account API keys

`GET /v1/workspaces/{slug}/account-api-keys`

Returns the workspace's account API keys without their values. Revoked keys are left out. Only admins and owners can list them.

### Parameters

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

### Returns

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

### Request

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

### Response

```json
[
  {
    "id": "Ak2WqH9sDf5T",
    "name": "Release CI",
    "role": "member",
    "lastFour": "cZaE",
    "createdAt": "2026-10-01T16:20:00.000Z"
  }
]
```

### 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 an account API key

`POST /v1/workspaces/{slug}/account-api-keys`

Creates a key that acts in this workspace with the given role. The response holds the key's value, which is never shown again. Only admins and owners can create account API keys, and only owners can grant the owner role.

### Parameters

- `slug` (string, in path, required): The workspace's slug or ID, such as acme.
- `name` (string, required): A name for the key, 1 to 100 characters, such as Release CI.
- `role` (string, one of: `owner`, `admin`, `member`, `viewer`, required): The role the key acts with. Only owners can choose owner.

### Returns

Returns an object with these fields. The status is 200. A new account API key with its value, which is never shown again.

- `id` (string, required): Unique ID of the account API key.
- `name` (string, required): The key's name.
- `role` (string, one of: `owner`, `admin`, `member`, `viewer`, required): The workspace role the key acts with.
- `secret` (string, required): The key, starting with ctk_. It is shown only in this response.

### Request

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

### Response

```json
{
  "id": "Ak2WqH9sDf5T",
  "name": "Release CI",
  "role": "member",
  "secret": "ctk_4mT8vQ2xR7nL9pW3kS6dH1jF5bY0cZaE"
}
```

### 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 an account API key

`PATCH /v1/workspaces/{slug}/account-api-keys/{id}`

Changes the key's name and role; its value stays the same. Only admins and owners can update account API keys, and only owners can change an owner key or grant the owner role.

### Parameters

- `slug` (string, in path, required): The workspace's slug or ID, such as acme.
- `id` (string, in path, required): The account API key's ID, such as Ak2WqH9sDf5T.
- `name` (string, required): A name for the key, 1 to 100 characters, such as Release CI.
- `role` (string, one of: `owner`, `admin`, `member`, `viewer`, required): The role the key acts with. Only owners can choose owner.

### 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}/account-api-keys/{id} \
  -H "Authorization: Bearer $CLANKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Release CI",
    "role": "member"
  }'
```

### 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.

## Revoke an account API key

`POST /v1/workspaces/{slug}/account-api-keys/{id}/revoke`

Revokes the key, so its next request fails with Unauthorized. Only admins and owners can revoke account API keys, and only owners can revoke an owner key.

### Parameters

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

### 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 POST https://api.qa.clankership.net/v1/workspaces/{slug}/account-api-keys/{id}/revoke \
  -H "Authorization: Bearer $CLANKER_API_KEY"
```

### 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.
