# Users & members

> List workspace members, add or remove them, send invitations and list workspaces.

Source: https://tickos.dev/docs/users

These endpoints manage the team of the workspace the API key belongs to. Use GET /v1/users to populate assignment dropdowns or validate user IDs before assigning tickets, POST /v1/members to add someone directly, POST /v1/invitations to invite someone by email, and GET /v1/accounts to list the workspaces of the key owner.

> **Roles:** Members created through the API get role member or viewer. Any role value other than "viewer" (for example "agent" or "admin") is stored as member. Owners cannot be created or removed through the API.

## GET /v1/users -- List members

Permission: read. Returns all workspace members ordered by join date (oldest first). No pagination: the full list is returned along with its count.

```json
{
  "data": [
    {
      "id": "usr-xxxxxxxx",
      "email": "agent@company.com",
      "full_name": "John Smith",
      "role": "member",
      "joined_at": "2024-01-15T10:00:00Z"
    }
  ],
  "count": 5
}
```

## POST /v1/members -- Add a member

Permission: write. Adds a user to the workspace directly, without an invitation flow. If no TickOS user exists with that email, one is created without a password (they can set one later with "Forgot password"). Any pending invitation for the same email in this workspace is marked as accepted. The email is trimmed and lowercased.

| Field | Type | Required | Description |
|---|---|---|---|
| email | string | Yes | Email of the user to add. |
| full_name | string | No | Name used only when a new user is created (defaults to the part of the email before @). Ignored for existing users. |
| role | string | No | viewer or member (default member). Any other value is stored as member. |

```bash
curl -X POST https://api.tickos.dev/v1/members \
  -H 'Authorization: Bearer sk_your_api_key' \
  -H 'Content-Type: application/json' \
  -d '{ "email": "jane@company.com", "full_name": "Jane Doe", "role": "member" }'
```

Returns 201:

```json
{
  "data": {
    "id": "usr-xxxxxxxx",
    "email": "jane@company.com",
    "full_name": "Jane Doe",
    "role": "member",
    "status": "active"
  }
}
```

| Status | When |
|---|---|
| 400 | Missing or invalid email. |
| 409 | The user is already a member of this workspace. |
| 429 | The plan user limit has been reached. This check runs before the membership check. |

## DELETE /v1/members/{userId} -- Remove a member

Permission: write. Removes the user from the workspace. The user account itself is not deleted. Returns { "success": true }.

| Status | When |
|---|---|
| 404 | The user is not a member of this workspace. |
| 400 | The user is an owner of the workspace (owners cannot be removed). |

```bash
curl -X DELETE https://api.tickos.dev/v1/members/usr-xxxxxxxx \
  -H 'Authorization: Bearer sk_your_api_key'
```

## POST /v1/invitations -- Invite a member

Permission: write. Creates an invitation valid for 7 days and emails an invitation link to the address. The user joins the workspace when they accept it. Same body as POST /v1/members (email, full_name, role). The invitation is attributed to the owner of the API key. If the email cannot be sent, the invitation is still created.

```bash
curl -X POST https://api.tickos.dev/v1/invitations \
  -H 'Authorization: Bearer sk_your_api_key' \
  -H 'Content-Type: application/json' \
  -d '{ "email": "jane@company.com", "role": "viewer" }'
```

Returns 201:

```json
{
  "data": { "id": "4f9c2a1e-7b3d-4c8e-9a6f-2d1e5b7c8a90", "email": "jane@company.com", "role": "viewer", "status": "pending" }
}
```

| Status | When |
|---|---|
| 400 | Missing or invalid email. |
| 409 | The user is already a member, or an invitation is already pending for this email. |
| 429 | The plan user limit has been reached. |

## GET /v1/accounts -- List workspaces

Permission: read. Lists the active workspaces that the owner of the API key belongs to, ordered by creation date. is_current marks the workspace the API key belongs to; all other endpoints always operate on that workspace.

| Field | Type | Description |
|---|---|---|
| id | string | Workspace ID. |
| name | string | Workspace name. |
| slug | string | Workspace slug. |
| logo_url | string \| null | Logo URL. |
| timezone | string | Workspace timezone. |
| status | string | Always active (inactive and deleted workspaces are excluded). |
| created_at | string | Creation date (ISO 8601). |
| role | string | Role of the key owner in that workspace (owner, member or viewer). |
| joined_at | string | When the key owner joined the workspace. |
| is_current | boolean | true for the workspace the API key belongs to. |

```json
{
  "data": [
    {
      "id": "acc_xxxxxxxx",
      "name": "Acme Support",
      "slug": "acme",
      "logo_url": null,
      "timezone": "UTC",
      "status": "active",
      "created_at": "2025-03-01T10:00:00Z",
      "role": "owner",
      "joined_at": "2025-03-01T10:00:00Z",
      "is_current": true
    }
  ],
  "meta": { "total": 1, "current_account_id": "acc_xxxxxxxx" }
}
```

If the key owner has no memberships, the response is { "data": [], "message": "No accounts found for this user" } without meta.
