---
sidebar_position: 2
title: Account
description: Agent self-service account management — view profile, list teams, update display name, upload avatar, change password, manage devices, and logout via the Firetell Agent API.
---

# Account

Self-service endpoints for agents to manage their own profile, teams, devices, and session. All endpoints require a valid **JWT token** with the `agent-api` audience (obtained via [Agent Login](/docs/rest-api/agent-api/auth#agent-login)).

## Endpoints

| Method  | Endpoint                              | Description                           |
| ------- | ------------------------------------- | ------------------------------------- |
| `GET`   | `/me`                                 | Get my profile                        |
| `GET`   | `/me/teams`                           | List my teams                         |
| `GET`   | `/me/teams/:id/agents`                | List other agents in my team          |
| `PATCH` | `/me`                                 | Update my display name                |
| `PATCH` | `/me/avatar`                          | Upload/change avatar                  |
| `PATCH` | `/me/password`                        | Change my password                    |
| `POST`  | `/me/devices/voip-push-token`         | Register VoIP push notification token |
| `POST`  | `/me/devices/notification-push-token` | Register notification push token      |
| `GET`   | `/me/devices`                         | List my registered devices            |
| `POST`  | `/me/logout`                          | Logout and remove device token        |

## Agent Profile Object

The profile object returned by `/me` endpoints:

| Field          | Type           | Description                                                  |
| -------------- | -------------- | ------------------------------------------------------------ |
| `id`           | string         | Unique agent ID (prefixed with `ag_`)                        |
| `username`     | string         | Agent login username                                         |
| `display_name` | string         | Agent display name                                           |
| `email`        | string \| null | Agent email address                                          |
| `avatar`       | string \| null | Avatar image URL                                             |
| `state`        | string         | Real-time presence: `available`, `incall`, `busy`, `offline` |
| `is_active`    | boolean        | Whether the agent account is active                          |
| `workspace_id` | string         | Workspace identifier                                         |
| `domain`       | string         | Agent's SIP domain                                           |
| `country_code` | string         | ISO 3166-1 alpha-2 country code                              |
| `created_at`   | string         | ISO 8601 creation timestamp                                  |
| `updated_at`   | string         | ISO 8601 last update timestamp                               |

---

## Get My Profile

```
GET /me
```

Retrieve the current authenticated agent's profile.

### Authentication

Requires `Bearer` JWT with `agent-api` audience.

### Request

```bash
curl -X GET "https://{workspace_id}.firetell.app/api/v1/me" \
  -H "Authorization: Bearer YOUR_AGENT_JWT"
```

### Response `200 OK`

```json
{
  "id": "ag_7f3a2b1c9d4e5f6a8b0c1d2e",
  "username": "johndoe",
  "display_name": "John Doe",
  "email": "john@example.com",
  "avatar": "https://storage.firetell.app/avatars/ag_7f3a2b1c.jpg",
  "role": "member",
  "state": "available",
  "is_active": true,
  "workspace_id": "my_workspace",
  "domain": "my_workspace.app.firetell.com",
  "country_code": "VN",
  "created_at": "2026-01-15T08:30:00.000Z",
  "updated_at": "2026-07-13T09:00:00.000Z"
}
```

### Error Responses

| Status | Description                                      |
| ------ | ------------------------------------------------ |
| `403`  | JWT audience is not `agent-api`                  |
| `404`  | Agent profile not found or account is not active |

---

## List My Teams

```
GET /me/teams
```

Retrieve a paginated list of teams that the current agent belongs to.

### Authentication

Requires `Bearer` JWT with `agent-api` audience.

### Query Parameters

| Parameter | Type   | Default | Description                       |
| --------- | ------ | ------- | --------------------------------- |
| `page`    | number | `1`     | Page number (min: 1)              |
| `limit`   | number | `10`    | Items per page (min: 1, max: 100) |

### Request

```bash
curl -X GET "https://{workspace_id}.firetell.app/api/v1/me/teams?page=1&limit=10" \
  -H "Authorization: Bearer YOUR_AGENT_JWT"
```

### Response `200 OK`

```json
{
  "data": [
    {
      "team_id": "te_a1b2c3d4e5f6g7h8",
      "team": {
        "id": "te_a1b2c3d4e5f6g7h8",
        "title": "Support Team",
        "workspace_id": "my_workspace",
        "agent_count": 5
      }
    },
    {
      "team_id": "te_x9y8z7w6v5u4t3s2",
      "team": {
        "id": "te_x9y8z7w6v5u4t3s2",
        "title": "Sales Team",
        "workspace_id": "my_workspace",
        "agent_count": 3
      }
    }
  ],
  "meta": {
    "total": 2,
    "page": 1,
    "limit": 10,
    "total_pages": 1
  }
}
```

### Item Fields

| Field     | Type   | Description                           |
| --------- | ------ | ------------------------------------- |
| `team_id` | string | Team ID                               |
| `team`    | object | Team details (id, title, agent_count) |

:::info
Agent roles are no longer stored per-team. Each agent has a single workspace-level role (`agent`, `leader`, or `supervisor`) set by an admin. See [Roles & Permissions](/docs/rest-api/agent-api/roles-permissions) for details.
:::

### Error Responses

| Status | Description                                      |
| ------ | ------------------------------------------------ |
| `403`  | JWT audience is not `agent-api`                  |
| `404`  | Agent profile not found or account is not active |

---

## List Team Agents

```
GET /me/teams/:id/agents
```

Retrieve a paginated list of other agents in a team that you belong to. The current agent is excluded from the results. This endpoint is designed for displaying teammate lists for messaging or calling.

### Authentication

Requires `Bearer` JWT with `agent-api` audience.

### Path Parameters

| Parameter | Type   | Description                          |
| --------- | ------ | ------------------------------------ |
| `id`      | string | Team ID (e.g. `te_a1b2c3d4e5f6g7h8`) |

### Query Parameters

| Parameter | Type   | Default | Description                       |
| --------- | ------ | ------- | --------------------------------- |
| `page`    | number | `1`     | Page number (min: 1)              |
| `limit`   | number | `10`    | Items per page (min: 1, max: 100) |

### Request

```bash
curl -X GET "https://{workspace_id}.firetell.app/api/v1/me/teams/te_a1b2c3d4e5f6g7h8/agents?page=1&limit=10" \
  -H "Authorization: Bearer YOUR_AGENT_JWT"
```

### Response `200 OK`

```json
{
  "data": [
    {
      "username": "jane_smith",
      "display_name": "Jane Smith",
      "avatar": "https://storage.firetell.app/avatars/ag_x9y8z7.jpg",
      "state": "available",
      "role": "leader"
    },
    {
      "username": "bob_wilson",
      "display_name": "Bob Wilson",
      "avatar": null,
      "state": "incall",
      "role": "member"
    },
    {
      "username": "alice_chen",
      "display_name": "Alice Chen",
      "avatar": "https://storage.firetell.app/avatars/ag_m3n4o5.jpg",
      "state": "offline",
      "role": "member"
    }
  ],
  "meta": {
    "total": 4,
    "page": 1,
    "limit": 10,
    "total_pages": 1
  }
}
```

### Item Fields

| Field          | Type           | Description                                                      |
| -------------- | -------------- | ---------------------------------------------------------------- |
| `username`     | string         | Agent username                                                   |
| `display_name` | string         | Agent display name                                               |
| `avatar`       | string \| null | Avatar URL                                                       |
| `state`        | string         | Presence state: `available`, `incall`, `busy`, `offline`         |
| `role`         | string         | Agent's workspace-level role: `agent`, `leader`, or `supervisor` |

:::info
The `role` field reflects the agent's **account-level role**, not a team-specific role. Roles are assigned globally per agent by workspace admins.
:::

### Error Responses

| Status | Description                                      |
| ------ | ------------------------------------------------ |
| `403`  | You are not a member of this team                |
| `404`  | Agent profile not found or account is not active |

---

## Update My Profile

```
PATCH /me
```

Update the current agent's display name. Only `display_name` can be modified by the agent. Other fields like `username`, `email`, `is_active`, and `country_code` can only be changed by workspace admins via the [Agents API](/docs/rest-api/workspace-api/agents).

### Authentication

Requires `Bearer` JWT with `agent-api` audience.

### Request Body

| Field          | Type   | Description                                             |
| -------------- | ------ | ------------------------------------------------------- |
| `display_name` | string | Display name (1–35 characters, letters and spaces only) |

### Request

```bash
curl -X PATCH "https://{workspace_id}.firetell.app/api/v1/me" \
  -H "Authorization: Bearer YOUR_AGENT_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "display_name": "John D."
  }'
```

### Response `200 OK`

Returns the updated agent profile object.

### Error Responses

| Status | Description                                      |
| ------ | ------------------------------------------------ |
| `403`  | JWT audience is not `agent-api`                  |
| `404`  | Agent profile not found or account is not active |

---

## Upload / Change Avatar

```
PATCH /me/avatar
```

Upload or replace the current agent's avatar image. The previous avatar (if any) is automatically deleted from storage.

### Authentication

Requires `Bearer` JWT with `agent-api` audience.

### Request Body

Send as `multipart/form-data` with a single file field:

| Field  | Type | Required | Description                                   |
| ------ | ---- | -------- | --------------------------------------------- |
| `file` | file | ✅       | Image file (max 5MB, must be an image format) |

### Request

```bash
curl -X PATCH "https://{workspace_id}.firetell.app/api/v1/me/avatar" \
  -H "Authorization: Bearer YOUR_AGENT_JWT" \
  -F "file=@/path/to/avatar.jpg"
```

### Response `200 OK`

Returns the updated agent profile object with the new `avatar` URL.

### Error Responses

| Status | Description                                      |
| ------ | ------------------------------------------------ |
| `400`  | File is missing or not an image format           |
| `403`  | JWT audience is not `agent-api`                  |
| `404`  | Agent profile not found or account is not active |

---

## Change My Password

```
PATCH /me/password
```

Change the current agent's login password. Unlike the admin [Change Password](/docs/rest-api/workspace-api/agents#change-agent-password) endpoint, this requires the **current password** for verification.

### Authentication

Requires `Bearer` JWT with `agent-api` audience.

### Request Body

| Field              | Type   | Required | Description                    |
| ------------------ | ------ | -------- | ------------------------------ |
| `current_password` | string | ✅       | Current (old) password         |
| `new_password`     | string | ✅       | New password (6–50 characters) |

### Request

```bash
curl -X PATCH "https://{workspace_id}.firetell.app/api/v1/me/password" \
  -H "Authorization: Bearer YOUR_AGENT_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "current_password": "oldPassword123",
    "new_password": "newSecurePassword456"
  }'
```

### Response `200 OK`

```json
{
  "message": "Password changed successfully"
}
```

### Error Responses

| Status | Description                                      |
| ------ | ------------------------------------------------ |
| `401`  | Current password is incorrect                    |
| `403`  | JWT audience is not `agent-api`                  |
| `404`  | Agent profile not found or account is not active |

:::caution
After changing the password, the agent's existing JWT tokens remain valid until expiration. No active sessions are terminated. The new password takes effect on the next login.
:::

---

## Register VoIP Push Notification Token

```
POST /me/devices/voip-push-token
```

Register or update a **VoIP push notification token** for the current device. This enables the agent to receive **incoming call notifications** via VoIP Push (APNs VoIP / FCM) even when the app is in the background or the WebSocket connection is closed.

If a device with the same `device_id` already exists, it will be updated with the new token and metadata.

:::info
This endpoint registers the **VoIP** push token used for incoming call pushes. To register a token for **regular notifications** (e.g., messages, alerts), use [`POST /me/devices/notification-push-token`](#register-notification-push-token) instead. The device record is created or updated (upserted by `device_id`).

On **iOS**, VoIP push (APNs VoIP) and regular push (APNs standard) use **different tokens**. Both must be registered separately.
On **Android/Web**, FCM handles both types — you may use the same FCM token for both endpoints.
:::

### Authentication

Requires `Bearer` JWT with `agent-api` audience.

### Request Body

| Field          | Type   | Required | Description                                              |
| -------------- | ------ | -------- | -------------------------------------------------------- |
| `push_token`   | string | ✅       | Push notification token (APNs VoIP token or FCM token)   |
| `device_id`    | string | ✅       | Unique device identifier (e.g., IDFV on iOS, Android ID) |
| `platform`     | string | ✅       | Device platform: `ios`, `android`, or `web`              |
| `os_version`   | string |          | OS version (e.g., `"17.5.1"`, `"14"`)                    |
| `app_version`  | string |          | Application version (e.g., `"1.2.0"`)                    |
| `device_model` | string |          | Device model (e.g., `"iPhone 15 Pro"`, `"Galaxy S24"`)   |

### Request

```bash
curl -X POST "https://{workspace_id}.firetell.app/api/v1/me/devices/voip-push-token" \
  -H "Authorization: Bearer YOUR_AGENT_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "push_token": "abc123...xyz",
    "device_id": "A1B2C3D4-E5F6-7890-ABCD-EF1234567890",
    "platform": "ios",
    "os_version": "17.5.1",
    "app_version": "1.2.0",
    "device_model": "iPhone 15 Pro"
  }'
```

### Response `200 OK`

```json
{
  "id": "dev_a1b2c3d4e5f6g7h8",
  "workspace_id": "my_workspace",
  "username": "johndoe",
  "push_token": "abc123...xyz",
  "device_id": "A1B2C3D4-E5F6-7890-ABCD-EF1234567890",
  "platform": "ios",
  "os_version": "17.5.1",
  "app_version": "1.2.0",
  "device_model": "iPhone 15 Pro",
  "voip_enabled": true,
  "notification_push_token": null,
  "last_active_at": "2026-07-13T10:00:00.000Z",
  "created_at": "2026-07-13T10:00:00.000Z",
  "updated_at": "2026-07-13T10:00:00.000Z"
}
```

:::tip
Call this endpoint every time the app launches or the push token refreshes to ensure the server always has the latest token. Stale tokens cannot receive push notifications.
:::

---

## Register Notification Push Token

```
POST /me/devices/notification-push-token
```

Register or update a **regular push notification token** for the current device. This enables the agent to receive **non-VoIP notifications** (e.g., chat messages, system alerts) via standard push (APNs / FCM).

The device must already be registered via [`POST /me/devices/voip-push-token`](#register-voip-push-notification-token).

:::info
On **iOS**, the standard APNs token is **different** from the VoIP APNs token. Both must be registered separately.
On **Android/Web**, FCM handles both VoIP and regular push — the same token can be used.
:::

### Authentication

Requires `Bearer` JWT with `agent-api` audience.

### Request Body

| Field                     | Type   | Required | Description                                              |
| ------------------------- | ------ | -------- | -------------------------------------------------------- |
| `notification_push_token` | string | ✅       | Regular push notification token (APNs standard or FCM)   |
| `device_id`               | string | ✅       | Unique device identifier (same as used in `/me/devices`) |
| `platform`                | string | ✅       | Device platform: `ios`, `android`, or `web`              |

### Request

```bash
curl -X POST "https://{workspace_id}.firetell.app/api/v1/me/devices/notification-push-token" \
  -H "Authorization: Bearer YOUR_AGENT_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "notification_push_token": "def456...uvw",
    "device_id": "A1B2C3D4-E5F6-7890-ABCD-EF1234567890",
    "platform": "ios"
  }'
```

### Response `200 OK`

```json
{
  "id": "dev_a1b2c3d4e5f6g7h8",
  "workspace_id": "my_workspace",
  "username": "johndoe",
  "push_token": "abc123...xyz",
  "device_id": "A1B2C3D4-E5F6-7890-ABCD-EF1234567890",
  "platform": "ios",
  "os_version": "17.5.1",
  "app_version": "1.2.0",
  "device_model": "iPhone 15 Pro",
  "voip_enabled": true,
  "notification_push_token": "def456...uvw",
  "last_active_at": "2026-07-13T10:05:00.000Z",
  "created_at": "2026-07-13T10:00:00.000Z",
  "updated_at": "2026-07-13T10:05:00.000Z"
}
```

### Error Responses

| Status | Description                                                                              |
| ------ | ---------------------------------------------------------------------------------------- |
| `403`  | JWT audience is not `agent-api`                                                          |
| `404`  | Device not found — register VoIP push token first via `POST /me/devices/voip-push-token` |

:::tip
Call this endpoint after registering the VoIP push token, or whenever the notification push token refreshes. On iOS, register both tokens on app launch:

1. `POST /me/devices/voip-push-token` — with the VoIP APNs token
2. `POST /me/devices/notification-push-token` — with the standard APNs token
   :::

---

## List My Devices

```
GET /me/devices
```

List all devices with registered push notification tokens for the current agent.

### Authentication

Requires `Bearer` JWT with `agent-api` audience.

### Response `200 OK`

```json
[
  {
    "id": "dev_a1b2c3d4e5f6g7h8",
    "workspace_id": "my_workspace",
    "username": "johndoe",
    "push_token": "abc123...xyz",
    "device_id": "A1B2C3D4-E5F6-7890-ABCD-EF1234567890",
    "platform": "ios",
    "os_version": "17.5.1",
    "app_version": "1.2.0",
    "device_model": "iPhone 15 Pro",
    "voip_enabled": true,
    "notification_push_token": "def456...uvw",
    "last_active_at": "2026-07-13T10:00:00.000Z"
  },
  {
    "id": "dev_x9y8z7w6v5u4t3s2",
    "workspace_id": "my_workspace",
    "username": "johndoe",
    "push_token": "def456...uvw",
    "device_id": "android-device-id-123",
    "platform": "android",
    "os_version": "14",
    "app_version": "1.2.0",
    "device_model": "Samsung Galaxy S24",
    "voip_enabled": true,
    "notification_push_token": "def456...uvw",
    "last_active_at": "2026-07-12T08:00:00.000Z"
  }
]
```

---

## Logout

```
POST /me/logout
```

Logout from a specific device. This removes the push notification token for the specified device, preventing it from receiving further call notifications.

:::caution
**Client applications MUST call this endpoint when the agent logs out.** If the agent simply closes the app without calling logout, the server will continue attempting to send push notifications to the stale token, which wastes resources and may cause the push provider (APNs/FCM) to throttle or revoke the token.

Inactive device registrations are automatically cleaned up after **30 days** of inactivity as a safety net, but explicit logout is always preferred.
:::

### Authentication

Requires `Bearer` JWT with `agent-api` audience.

### Request Body

| Field       | Type   | Required | Description                                               |
| ----------- | ------ | -------- | --------------------------------------------------------- |
| `device_id` | string | ✅       | The device identifier used during push token registration |

### Request

```bash
curl -X POST "https://{workspace_id}.firetell.app/api/v1/me/logout" \
  -H "Authorization: Bearer YOUR_AGENT_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "device_id": "A1B2C3D4-E5F6-7890-ABCD-EF1234567890"
  }'
```

### Response `200 OK`

```json
{
  "message": "Logged out successfully"
}
```

:::info
This endpoint is **idempotent** — calling it multiple times with the same `device_id` always returns success, even if the device was already unregistered.
:::

### What happens on logout

1. The push notification token for the specified device is deleted
2. If the agent has no more devices with push tokens **and** no active WebSocket connections, their presence state transitions to `offline`
3. The JWT token itself remains valid until expiration — logout only removes the push notification registration
