# 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.qa.clankership.net/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.qa.clankership.net/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.
      - `lastSeenAt` (string, required): When the session last reported, as an ISO 8601 timestamp.
      - `live` (boolean, required): Whether the session reported 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.
    - `summary` (nullable string, required): What the work is and why, in Markdown, or null.
    - `status` (object, required): A step in a team's workflow, such as In Planning or In Build. See [the TicketStatus object](https://docs.qa.clankership.net/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 In Build.
      - `category` (string, one of: `backlog`, `planning`, `build`, `review`, `shipped`, `canceled`, required): The fixed stage the status belongs to: backlog, planning, build, review, shipped 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.qa.clankership.net/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.qa.clankership.net/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.
      - `total` (number, required): How many items there are.
    - `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.qa.clankership.net/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",
              "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",
          "summary": "Readers cannot find a page without browsing the sidebar. Add a search box to the docs header.",
          "status": {
            "id": "St3BdV6nHs9D",
            "name": "In 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,
            "total": 3
          },
          "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.qa.clankership.net/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.qa.clankership.net/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",
            "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.qa.clankership.net/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.
