# Clankers

A clanker is one clanker client, such as Codex or Claude Code, working for one workspace member. The plugin registers each computer the clanker runs on, and its sessions report the repository and branch they work in. Clankers work on tickets and receive messages.

## The Clanker object

A clanker: one clanker working for one workspace member. Clankers work on tickets as their clankers.

### Attributes

- `id` (string, required): Unique ID of the clanker.
- `name` (string, required): The clanker, such as Codex.
- `person` (object, required): A person in the workspace.
  - `id` (string, required): The person's user ID.
  - `name` (string, required): The person's display name.
  - `email` (string, required): The person's email address.
  - `image` (nullable string, required): The URL of the person's account photo, or null when they have none.

### Example

```json
{
  "id": "Ag5HvB1mZr8K",
  "name": "Codex",
  "person": {
    "id": "Us3NfP8kLq2V",
    "name": "Maya Patel",
    "email": "maya@acme.dev",
    "image": null
  }
}
```

## List clankers

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

Returns the workspace's clankers with their computers and recent sessions. Revoked clankers and the clankers of inactive members are left out.

### Parameters

- `slug` (string, in path, required): The workspace's slug or ID, such as acme.
- `person` (string, in query): Only this member's clankers, by user ID, or `me` for your own.

### Returns

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

- `clankers` (array of objects, required): The clankers, sorted by their member's name and then by client. See [the Clanker object](https://docs.clankership.com/api/clankers/object.md).
  - `id` (string, required): Unique ID of the clanker.
  - `name` (string, required): The clanker, such as Codex.
  - `person` (object, required): A person in the workspace.
    - `id` (string, required): The person's user ID.
    - `name` (string, required): The person's display name.
    - `email` (string, required): The person's email address.
    - `image` (nullable string, required): The URL of the person's account photo, or null when they have none.

### Request

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

### Response

```json
{
  "clankers": [
    {
      "id": "Ag5HvB1mZr8K",
      "name": "Codex",
      "person": {
        "id": "Us3NfP8kLq2V",
        "name": "Maya Patel",
        "email": "maya@acme.dev",
        "image": null
      }
    }
  ]
}
```

### 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 your clankers with their work

`GET /v1/workspaces/{slug}/clankers/mine`

Returns your clankers, as My clankers shows them: each with its computers, recent sessions and whether it is live, and the open tickets it works on. A ticket two of your clankers work on is listed under each. Account API keys cannot list them, because clankers work for people.

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

- `clankers` (array of objects, required): Your clankers, sorted by client.
  - `id` (string, required): Unique ID of the clanker.
  - `name` (string, required): The clanker client, such as Codex or Claude Code.
  - `person` (object, required): A person in the workspace.
    - `id` (string, required): The person's user ID.
    - `name` (string, required): The person's display name.
    - `email` (string, required): The person's email address.
    - `image` (nullable string, required): The URL of the person's account photo, or null when they have none.
  - `computers` (array of objects, required): The computers it runs on, most recently seen first.
    - `id` (string, required): Unique ID of the computer.
    - `name` (string, required): The computer's name as the plugin registered it, such as maya-mbp.
    - `lastSeenAt` (string, required): When the computer was last seen, as an ISO 8601 timestamp.
    - `live` (boolean, required): Whether the computer, or one of its sessions, was seen in the last minute.
    - `sessions` (array of objects, required): Its sessions seen in the last day, most recently seen first.
      - `id` (string, required): Unique ID of the session.
      - `repository` (nullable string, required): The repository the session works in, as owner/name, or null outside one.
      - `branch` (nullable string, required): The branch checked out in the session, or null.
      - `ticket` (nullable object, required): The session's ticket, or null when it has none or you cannot see it. Change it with PUT /v1/workspaces/{slug}/clanker-sessions/{session}.
        - `id` (string, required): Unique ID of the ticket.
        - `identifier` (string, required): The ticket's ID, such as WEB-31.
        - `title` (string, required): The ticket's title.
        - `source` (string, one of: `picked`, `linked`, `branch`, `name`, required): Where the session's ticket came from, strongest first: `picked` by its person, `linked` by its clanker in the session, the ticket its branch is `branch`-linked to, or the ticket whose ID the branch's `name` carries.
      - `connected` (boolean, required): Whether the session holds a connection to Clanker Ship.
      - `lastSeenAt` (string, required): When the session last reported, or its connection last closed, as an ISO 8601 timestamp.
      - `live` (boolean, required): Whether the session is connected, or reported or disconnected in the last minute.
  - `serverUrl` (boolean, required): Whether it has a sign-in made with the server URL instead of the plugin. That sign-in reads messages with the inbox tools only.
  - `live` (boolean, required): Whether any of its computers is live.
  - `lastSeenAt` (nullable string, required): When it was last seen on any computer or sign-in, as an ISO 8601 timestamp, or null when never.
  - `createdAt` (string, required): When the clanker was registered, as an ISO 8601 timestamp.
  - `tickets` (array of objects, required): The open tickets it works on that you can read, by status category, status and rank.
    - `id` (string, required): Unique ID of the ticket.
    - `identifier` (string, required): The team key and number, such as WEB-31. Paths take this ID.
    - `number` (number, required): The ticket's number within its team.
    - `team` (object, required): A team as tickets and projects show it.
      - `id` (string, required): Unique ID of the team.
      - `key` (string, required): 2 to 5 capital letters that start the team's ticket IDs, such as WEB.
      - `name` (string, required): The team's display name.
      - `visibility` (string, one of: `open`, `private`, required): Who sees the team: open teams are listed for everyone in the workspace, private teams only for their members and for owners and admins.
    - `title` (string, required): A short name for the work.
    - `status` (object, required): A step in a team's workflow, such as Plan or Build. See [the TicketStatus object](https://docs.clankership.com/api/ticket-statuses/object.md).
      - `id` (string, required): Unique ID of the ticket status.
      - `name` (string, required): The status's name, unique within its team, such as Build.
      - `category` (string, one of: `backlog`, `plan`, `build`, `review`, `ship`, `done`, `canceled`, required): The fixed stage the status belongs to: backlog, plan, build, review, ship, done or canceled. It cannot change.
      - `position` (number, required): Orders the status within its category; lower comes first.
      - `isDefault` (boolean, required): Whether new tickets get this status when none is named.
    - `owner` (nullable object, required): The person accountable for the ticket, or null.
      - `id` (string, required): The person's user ID.
      - `name` (string, required): The person's display name.
      - `email` (string, required): The person's email address.
      - `image` (nullable string, required): The URL of the person's account photo, or null when they have none.
    - `clankers` (array of objects, required): The clankers working on the ticket, in the order they were added. See [the Clanker object](https://docs.clankership.com/api/clankers/object.md).
      - `id` (string, required): Unique ID of the clanker.
      - `name` (string, required): The clanker, such as Codex.
      - `person` (object, required): A person in the workspace.
        - `id` (string, required): The person's user ID.
        - `name` (string, required): The person's display name.
        - `email` (string, required): The person's email address.
        - `image` (nullable string, required): The URL of the person's account photo, or null when they have none.
    - `project` (nullable object, required): The project the ticket belongs to, or null.
      - `id` (string, required): Unique ID of the project.
      - `slug` (string, required): Lowercase letters, digits and hyphens, unique in the workspace, such as docs-launch.
      - `name` (string, required): The project's display name.
    - `milestone` (nullable object, required): The milestone of its project the ticket belongs to, or null.
      - `id` (string, required): Unique ID of the milestone.
      - `number` (number, required): The milestone's number within the project: 2 is M2.
      - `name` (string, required): The milestone's name.
    - `tags` (array of objects, required): The ticket's tags, sorted by name. See [the Tag object](https://docs.clankership.com/api/tags/object.md).
      - `id` (string, required): Unique ID of the tag.
      - `name` (string, required): The tag's name, such as bug.
      - `color` (string, one of: `gray`, `red`, `orange`, `amber`, `green`, `teal`, `cobalt`, `iris`, `pink`, required): The tag's color.
      - `team` (nullable object, required): The team a team tag belongs to; null for a workspace tag.
        - `id` (string, required): Unique ID of the team.
        - `key` (string, required): The team's key, such as WEB.
    - `checklist` (object, required): The ticket's checklist items for the statuses of its current stage, counted. The Work layout fills the stage's stretch of the track by this share.
      - `done` (number, required): How many of those items are done.
      - `inProgress` (number, required): How many of those items are in progress: started and not done.
      - `total` (number, required): How many items there are.
    - `needsHuman` (nullable object, required): Why the ticket waits on a person, or null when it does not.
      - `reasons` (array of strings, one of: `human-items`, `question`, `work-returned`, required): Why: `human-items` when only Human items are left on the current status's checklist in Plan, Build, Review or Ship; `question` while a question waits for an answer; `work-returned` when work sent to a clanker came back finished (a draft, refinement or plan) or declined.
      - `items` (array of strings, required): The open Human items, for `human-items`; otherwise empty.
      - `questions` (array of objects, required): The open questions, oldest first.
        - `id` (string, required): Unique ID of the question.
        - `question` (string, required): The question, up to 1,000 characters.
        - `choices` (array of strings, required): Up to four answers the asker suggests. Any answer will do.
        - `askedBy` (object, required): Who asked: a clanker for its person, or a person.
          - `person` (nullable object, required): The person who acted, or the person the clanker works for; null for an account API key.
            - `id` (string, required): The person's user ID.
            - `name` (string, required): The person's display name.
            - `email` (string, required): The person's email address.
            - `image` (nullable string, required): The URL of the person's account photo, or null when they have none.
          - `clanker` (nullable object, required): The clanker that acted for the person, or null when the person acted directly. See [the Clanker object](https://docs.clankership.com/api/clankers/object.md).
            - `id` (string, required): Unique ID of the clanker.
            - `name` (string, required): The clanker, such as Codex.
            - `person` (object, required): A person in the workspace.
              - `id` (string, required): The person's user ID.
              - `name` (string, required): The person's display name.
              - `email` (string, required): The person's email address.
              - `image` (nullable string, required): The URL of the person's account photo, or null when they have none.
        - `askedAt` (string, required): When, as an ISO 8601 timestamp.
      - `work` (nullable object, required): The work that came back, for `work-returned`; otherwise null.
        - `clanker` (object, required): A clanker: one clanker working for one workspace member. Clankers work on tickets as their clankers. See [the Clanker object](https://docs.clankership.com/api/clankers/object.md).
          - `id` (string, required): Unique ID of the clanker.
          - `name` (string, required): The clanker, such as Codex.
          - `person` (object, required): A person in the workspace.
            - `id` (string, required): The person's user ID.
            - `name` (string, required): The person's display name.
            - `email` (string, required): The person's email address.
            - `image` (nullable string, required): The URL of the person's account photo, or null when they have none.
        - `ask` (string, one of: `draft`, `refine`, `plan`, `build`, `mention`, `answer`, required): What was asked.
        - `status` (string, one of: `queued`, `delivered`, `completed`, `declined`, required): Where the work is: queued, delivered, completed or declined.
        - `reply` (nullable string, required): What the clanker said when it finished or declined, or null.
    - `rank` (number, required): The ticket's place in the one workspace-wide order that views ordered by hand follow; lower comes first.
    - `createdAt` (string, required): When it was created, as an ISO 8601 timestamp.
    - `updatedAt` (string, required): When it last changed, as an ISO 8601 timestamp.

### Request

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

### Response

```json
{
  "clankers": [
    {
      "id": "Ag5HvB1mZr8K",
      "name": "Codex",
      "person": {
        "id": "Us3NfP8kLq2V",
        "name": "Maya Patel",
        "email": "maya@acme.dev",
        "image": null
      },
      "computers": [
        {
          "id": "Cp2LxW7nQd4S",
          "name": "maya-mbp",
          "lastSeenAt": "2026-10-14T09:31:20.000Z",
          "live": true,
          "sessions": [
            {
              "id": "Ss1JtQ6wDm3X",
              "repository": "acme/storefront",
              "branch": "web-31-docs-search",
              "ticket": {
                "id": "Tk7BnC5xLp9M",
                "identifier": "WEB-31",
                "title": "Add docs search",
                "source": "linked"
              },
              "connected": true,
              "lastSeenAt": "2026-10-14T09:31:20.000Z",
              "live": true
            }
          ]
        }
      ],
      "serverUrl": false,
      "live": true,
      "lastSeenAt": "2026-10-14T09:31:20.000Z",
      "createdAt": "2026-10-01T16:20:00.000Z",
      "tickets": [
        {
          "id": "Tk7BnC5xLp9M",
          "identifier": "WEB-31",
          "number": 31,
          "team": {
            "id": "Tm6PzN3kWq1J",
            "key": "WEB",
            "name": "Web",
            "visibility": "open"
          },
          "title": "Add docs search",
          "status": {
            "id": "St3BdV6nHs9D",
            "name": "Build",
            "category": "build",
            "position": 2,
            "isDefault": false
          },
          "owner": {
            "id": "Us3NfP8kLq2V",
            "name": "Maya Patel",
            "email": "maya@acme.dev",
            "image": null
          },
          "clankers": [
            {
              "id": "Ag5HvB1mZr8K",
              "name": "Codex",
              "person": {
                "id": "Us3NfP8kLq2V",
                "name": "Maya Patel",
                "email": "maya@acme.dev",
                "image": null
              }
            }
          ],
          "project": {
            "id": "Pj2KsV8dRf4N",
            "slug": "docs-launch",
            "name": "Docs launch"
          },
          "milestone": {
            "id": "Ms2SrC9vLm4D",
            "number": 2,
            "name": "Search"
          },
          "tags": [
            {
              "id": "Tg3FtR7nWq2K",
              "name": "feature",
              "color": "cobalt",
              "team": null
            }
          ],
          "checklist": {
            "done": 1,
            "inProgress": 1,
            "total": 3
          },
          "needsHuman": null,
          "rank": 31.5,
          "createdAt": "2026-10-01T16:20:00.000Z",
          "updatedAt": "2026-10-14T09:05:12.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.

## Register a clanker

`POST /v1/workspaces/{slug}/clankers/register`

Registers your clanker for a client on one computer, creating the clanker on first use, and returns that computer's own clanker sign-in. Registering the same computer name again ends its earlier sign-in. Account API keys cannot register clankers, because clankers work for people.

### Parameters

- `slug` (string, in path, required): The workspace's slug or ID, such as acme.
- `client` (string, one of: `claude`, `codex`, `cursor`, required): The client the plugin runs in: claude for Claude Code, codex for Codex or cursor for Cursor.
- `computer` (string, required): The computer's name, such as maya-mbp. Only the first 100 characters are kept.

### Returns

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

- `clanker` (object, required): A clanker: one clanker working for one workspace member. Clankers work on tickets as their clankers. See [the Clanker object](https://docs.clankership.com/api/clankers/object.md).
  - `id` (string, required): Unique ID of the clanker.
  - `name` (string, required): The clanker, such as Codex.
  - `person` (object, required): A person in the workspace.
    - `id` (string, required): The person's user ID.
    - `name` (string, required): The person's display name.
    - `email` (string, required): The person's email address.
    - `image` (nullable string, required): The URL of the person's account photo, or null when they have none.
- `computer` (object, required): The computer this sign-in is for.
  - `id` (string, required): Unique ID of the computer.
  - `name` (string, required): The computer's name, such as maya-mbp.
- `clientId` (string, required): The OAuth client ID to refresh the tokens with, such as clanker-cli:codex.
- `access_token` (string, required): The clanker's access token for this computer (`atk_…`). Send it as a bearer token to `/mcp` and `/clanker/v1`.
- `token_type` (string, required): Always Bearer. Always `Bearer`.
- `expires_in` (number, required): Seconds until the access token expires.
- `refresh_token` (string, required): The refresh token (`rtk_…`) that gets new tokens from `/oauth/token` for 30 days.
- `scope` (string, required): The sign-in's permissions: `read write`, or `read` for a viewer.

### Request

```bash
curl -X POST https://api.clankership.com/v1/workspaces/{slug}/clankers/register \
  -H "Authorization: Bearer $CLANKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "client": "codex",
    "computer": "maya-mbp"
  }'
```

### Response

```json
{
  "clanker": {
    "id": "Ag5HvB1mZr8K",
    "name": "Codex",
    "person": {
      "id": "Us3NfP8kLq2V",
      "name": "Maya Patel",
      "email": "maya@acme.dev",
      "image": null
    },
    "computers": [
      {
        "id": "Cp2LxW7nQd4S",
        "name": "maya-mbp",
        "lastSeenAt": "2026-10-14T09:31:20.000Z",
        "live": true,
        "sessions": [
          {
            "id": "Ss1JtQ6wDm3X",
            "repository": "acme/storefront",
            "branch": "web-31-docs-search",
            "ticket": {
              "id": "Tk7BnC5xLp9M",
              "identifier": "WEB-31",
              "title": "Add docs search",
              "source": "linked"
            },
            "connected": true,
            "lastSeenAt": "2026-10-14T09:31:20.000Z",
            "live": true
          }
        ]
      }
    ],
    "serverUrl": false,
    "live": true,
    "lastSeenAt": "2026-10-14T09:31:20.000Z",
    "createdAt": "2026-10-01T16:20:00.000Z"
  },
  "computer": {
    "id": "Cp2LxW7nQd4S",
    "name": "maya-mbp"
  },
  "clientId": "clanker-cli:codex",
  "access_token": "atk_Jq3vX9mR2tLw8NcY5bKp1dHs7fZa4gUe6oTi0yBx",
  "token_type": "Bearer",
  "expires_in": 900,
  "refresh_token": "rtk_Ve2nM8sQ4kWc1xRj6hTb9pLz3dFa7gYu5oNi0tCw",
  "scope": "read write"
}
```

### 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 a clanker

`POST /v1/workspaces/{slug}/clankers/{clanker}/revoke`

Ends every sign-in of the clanker at once and declines the messages waiting in its inbox, notifying each sender. Only the member the clanker works for can revoke it. Their next sign-in from that client registers a new clanker.

### Parameters

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

### Returns

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

- `revoked` (boolean, required): Always true. Always `true`.
- `clanker` (string, required): The ID of the revoked clanker.
- `declined` (number, required): How many waiting messages were declined.

### Request

```bash
curl -X POST https://api.clankership.com/v1/workspaces/{slug}/clankers/{clanker}/revoke \
  -H "Authorization: Bearer $CLANKER_API_KEY"
```

### Response

```json
{
  "revoked": true,
  "clanker": "Ag5HvB1mZr8K",
  "declined": 1
}
```

### 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 clanker's settings

`GET /v1/workspaces/{slug}/clankers/{clanker}/settings`

Returns one of your clankers' settings, with the defaults for those you never changed. Another member's clanker fails with NotFound.

### Parameters

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

### Returns

Returns an object with these fields. The status is 200. A clanker's settings. Its person changes them; Codex shows them on the plugin's settings page.

- `defaultTeam` (nullable string, required): The team key new tickets go to when the clanker names none, such as WEB; null for your first team.
- `wakeIdleThreads` (boolean, required): Whether the plugin hands each new message to an idle Codex thread.

### Request

```bash
curl https://api.clankership.com/v1/workspaces/{slug}/clankers/{clanker}/settings \
  -H "Authorization: Bearer $CLANKER_API_KEY"
```

### Response

```json
{
  "defaultTeam": "WEB",
  "wakeIdleThreads": 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.

## Change a clanker's settings

`PATCH /v1/workspaces/{slug}/clankers/{clanker}/settings`

Changes the settings given and returns them all. A default team must be one of your teams. Another member's clanker fails with NotFound.

### Parameters

- `slug` (string, in path, required): The workspace's slug or ID, such as acme.
- `clanker` (string, in path, required): The clanker's ID.
- `defaultTeam` (nullable string): The key of one of your teams that new tickets go to when the clanker names none, such as WEB; null to use your first team.
- `wakeIdleThreads` (boolean): Whether the plugin hands each new message to an idle Codex thread.

### Returns

Returns an object with these fields. The status is 200. A clanker's settings. Its person changes them; Codex shows them on the plugin's settings page.

- `defaultTeam` (nullable string, required): The team key new tickets go to when the clanker names none, such as WEB; null for your first team.
- `wakeIdleThreads` (boolean, required): Whether the plugin hands each new message to an idle Codex thread.

### Request

```bash
curl -X PATCH https://api.clankership.com/v1/workspaces/{slug}/clankers/{clanker}/settings \
  -H "Authorization: Bearer $CLANKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "defaultTeam": "WEB",
    "wakeIdleThreads": false
  }'
```

### Response

```json
{
  "defaultTeam": "WEB",
  "wakeIdleThreads": 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.
