# Members

A member is a person in a workspace with one role: owner, admin, member or viewer. Owners and admins manage members and invites, members do the work, and viewers only read.

## The Member object

A person in the workspace and their role.

### Attributes

- `userId` (string, required): The member's user ID.
- `name` (string, required): The member's display name.
- `email` (string, required): The member's email address.
- `image` (nullable string, required): URL of the member's profile photo, or null.
- `role` (string, one of: `owner`, `admin`, `member`, `viewer`, required): Owners and admins manage the workspace and its people, members do the work, and viewers only read.
- `joinedAt` (string, required): When the person joined the workspace, as an ISO 8601 timestamp.
- `teams` (array of strings, required): Names of the teams the member is in, sorted alphabetically, such as Web.

### Example

```json
{
  "userId": "Us3NfP8kLq2V",
  "name": "Maya Patel",
  "email": "maya@acme.dev",
  "image": "https://images.clankertest.com/users/Us3NfP8kLq2V/profile-Ph8KcV2nRx4M.webp",
  "role": "owner",
  "joinedAt": "2026-10-01T16:20:00.000Z",
  "teams": [
    "Web"
  ]
}
```

## List members

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

Returns the workspace's active members with their roles and teams, sorted by name. Any member can list members.

### Parameters

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

### Returns

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

### Request

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

### Response

```json
[
  {
    "userId": "Us3NfP8kLq2V",
    "name": "Maya Patel",
    "email": "maya@acme.dev",
    "image": "https://images.clankertest.com/users/Us3NfP8kLq2V/profile-Ph8KcV2nRx4M.webp",
    "role": "owner",
    "joinedAt": "2026-10-01T16:20:00.000Z",
    "teams": [
      "Web"
    ]
  }
]
```

### 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 member's role

`PATCH /v1/workspaces/{slug}/members/{userId}`

Sets a member's role and records a `member.role_changed` event. Only owners and admins can change roles, and admins cannot change an owner's role or make anyone an owner. The last owner cannot be demoted.

### Parameters

- `slug` (string, in path, required): The workspace's slug or ID, such as acme.
- `userId` (string, in path, required): The member's user ID, such as Us9DcT4wHn6R.
- `role` (string, one of: `owner`, `admin`, `member`, `viewer`, required): The member's new role: owner, admin, member or viewer.

### 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}/members/{userId} \
  -H "Authorization: Bearer $CLANKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "admin"
  }'
```

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

## Remove a member

`DELETE /v1/workspaces/{slug}/members/{userId}`

Removes the person from the workspace and its teams, and records a `member.removed` event. Only owners and admins can remove members, and admins cannot remove owners. Nobody can remove themselves or the last owner.

### Parameters

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

### 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 DELETE https://api.qa.clankership.net/v1/workspaces/{slug}/members/{userId} \
  -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.

## List members with your role

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

Returns the workspace's active members, plus your ID and role, so a client can tell which members you may manage. Any member can call it.

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

- `userId` (string, required): Your user ID, or the account API key's ID.
- `role` (string, one of: `owner`, `admin`, `member`, `viewer`, required): Your role in the workspace: owner, admin, member or viewer.
- `members` (array of objects, required): The workspace's active members, sorted by name. See [the Member object](https://docs.qa.clankership.net/api/members/object.md).
  - `userId` (string, required): The member's user ID.
  - `name` (string, required): The member's display name.
  - `email` (string, required): The member's email address.
  - `image` (nullable string, required): URL of the member's profile photo, or null.
  - `role` (string, one of: `owner`, `admin`, `member`, `viewer`, required): Owners and admins manage the workspace and its people, members do the work, and viewers only read.
  - `joinedAt` (string, required): When the person joined the workspace, as an ISO 8601 timestamp.
  - `teams` (array of strings, required): Names of the teams the member is in, sorted alphabetically, such as Web.

### Request

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

### Response

```json
{
  "userId": "Us3NfP8kLq2V",
  "role": "owner",
  "members": [
    {
      "userId": "Us3NfP8kLq2V",
      "name": "Maya Patel",
      "email": "maya@acme.dev",
      "image": "https://images.clankertest.com/users/Us3NfP8kLq2V/profile-Ph8KcV2nRx4M.webp",
      "role": "owner",
      "joinedAt": "2026-10-01T16:20:00.000Z",
      "teams": [
        "Web"
      ]
    }
  ]
}
```

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