
# 团队 API

您的团队是指除您之外在您的账户中工作的所有人员（包括管理员、坐席和只读查看者），以及您已发送的邀请和您将他们组织成的部门。团队 API 是 **设置 → 团队** 的程序化版本：用于添加和移除人员、设置每个人的查看和操作权限、发送和催促邀请，以及管理部门。

以下所有端点均相对于基础 URL `https://api.youraiconnector.com/v1`。有关本页面所有内容的仪表板版本，请参阅 [团队管理](../settings/team-management.md)。

---

## 身份验证：这些端点需要已登录的用户

**这是 API 中唯一无法使用 API 密钥的部分。** 除了 [部门](#departments) 端点外，每个 `/team` 端点都必须使用来自已登录会话的 **Firebase ID 令牌** 进行调用：

```
Authorization: Bearer <Firebase ID token>
```

如果发送 API 密钥，请求将被拒绝并返回 `401`：

```json
{
  "success": false,
  "error_code": 401,
  "error": "This endpoint requires a Firebase ID token (Authorization: Bearer <token>)."
}
```

原因是这些端点会根据**谁已登录**来决定操作：您的角色、您被允许授予他人的权限上限，以及您当前是否正在另一个账户内工作。API 密钥是集成而非个人，因此这些规则无法应用于它。

实际上，这意味着团队 API 适用于具有已登录 <span data-t="appName">Your AI Connector</span> 用户的第一方应用程序（请参阅 [身份验证 → Firebase ID 令牌](authentication.md#4-firebase-id-token-first-party-only)）。服务器到服务器的集成无法管理团队成员——无法在应用程序外部生成这些令牌。

> **例外情况：** 四个 [部门](#departments) 端点是普通的 API 端点。它们像 API 的其余部分一样接受您的 API 密钥，同时也接受已登录的会话。

本页面上的每个响应都遵循通常的信封格式：`success: true` 以及顶层的端点字段，或者在出错时返回带有 `error` 和 `error_code` 的 `success: false`。

---

## 角色和权限

每个团队成员都有一个**角色**，该角色设定了他们在应用程序 12 个区域中的默认访问权限。随后，您可以覆盖各个区域的权限。

| 角色 | 值 | 摘要 |
|---|---|---|
| 管理员 | `admin` | 除所有者级别的计费操作外，拥有所有权限。 |
| 编辑者 | `editor` | 可以创建和更改内容。在应用程序中显示为 **坐席**。 |
| 查看者 | `viewer` | 只读。 |

每个区域被设置为四个级别之一：`none`（隐藏）、`view`（只读）、`edit`（创建和更改）、`full`（包括删除）。

| 区域 | 管理员 | 编辑者 | 查看者 |
|---|---|---|---|
| `campaigns` | full | edit | view |
| `contacts` | full | edit | view |
| `messages` | full | edit | view |
| `appointments` | full | edit | view |
| `settings` | edit | view | none |
| `billing` | edit | none | none |
| `team_management` | edit | none | none |
| `analytics` | full | view | view |
| `phone_numbers` | edit | none | none |
| `integrations` | edit | none | none |
| `faqs` | full | edit | view |
| `daily_summaries` | full | view | view |

若要偏离角色的默认设置，请发送 `permission_overrides`（一个 `{ "area": ..., "level": ... }` 对象数组）。每个条目都会替换该角色在特定区域的默认设置；未列出的所有内容都将保持角色默认值。

```json
"permission_overrides": [
  { "area": "analytics", "level": "full" },
  { "area": "billing", "level": "none" }
]
```

**谁可以调用这些端点**

- **账户所有者**始终拥有所有权限。
- 团队成员需要 `view` 处的 `team_management` 权限才能读取花名册和邀请列表，并需要 `edit` 处的权限才能进行添加、更改、暂停、移除、邀请、取消或重新发送操作。管理员默认拥有 `edit` 权限；编辑者和查看者拥有 `none` 权限，因此默认情况下只有管理员可以管理团队。
- **任何人不得授予高于自身权限的访问权限。** 如果您尝试授予某人您自己都不具备的权限级别，或者尝试编辑、暂停或移除权限范围已超过您的人员，请求将被拒绝，并返回 `403` 以及说明相关区域的消息。

---

## 团队成员对象

`GET /team/members` 会为每位成员返回以下对象之一：

| 字段 | 类型 | 描述 |
|---|---|---|
| `member_uid` | string | 成员自己的用户 ID。这是下方路径中的 `{memberUid}`。 |
| `account_owner_uid` | string | 他们所属的账户。 |
| `member_email` | string | 他们的电子邮件地址。 |
| `member_display_name` | string | 他们在应用程序中显示的名称。 |
| `role` | string | `admin`、`editor` 或 `viewer`。 |
| `permission_overrides` | array | 他们在各区域的例外设置。`[]` 表示他们完全遵循角色默认设置。 |
| `status` | string | `active` 或 `suspended`。 |
| `auto_assign_enabled` | boolean \| null | 是否可以将新联系人自动分配给他们。`null` 表示从未更改，其行为与 `true` 相同。 |
| `created_by` | string | 添加他们的人。 |
| `created_at` | string \| null | ISO 8601 时间戳。 |
| `updated_at` | string \| null | ISO 8601 时间戳。 |

已移除的成员不会被返回——该列表仅包含活跃成员和已暂停成员。

> **可见性限制在此处仅为写入权限。** `contact_scope`、`contact_scope_axes` 和 `sub_account_access`（请参阅[限制成员可见范围](#limiting-what-a-member-can-see)）可以在创建、更新和邀请时设置，但此端点不会返回它们。

---

## 列出团队成员

`GET /team/members`

返回花名册以及您套餐的席位统计信息，以便您可以显示“已用 3 个，共 5 个席位”，并了解何时即将无法发送邀请。

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/team/members" \
  -H "Authorization: Bearer FIREBASE_ID_TOKEN"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/team/members", {
  headers: { Authorization: `Bearer ${idToken}` },
});
const { members, seat_limit, seats_used } = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/team/members",
    headers={"Authorization": f"Bearer {id_token}"},
)
data = res.json()
```

**响应**

```json
{
  "success": true,
  "members": [
    {
      "account_owner_uid": "owner_uid_123",
      "member_uid": "uid_alice",
      "member_email": "alice@example.com",
      "member_display_name": "Alice Chen",
      "role": "admin",
      "permission_overrides": [],
      "status": "active",
      "auto_assign_enabled": true,
      "created_by": "owner_uid_123",
      "created_at": "2026-05-01T10:00:00.000Z",
      "updated_at": "2026-06-02T09:15:00.000Z"
    }
  ],
  "seat_limit": 5,
  "seats_used": 3
}
```

当您的套餐没有席位上限时，`seat_limit` 为 `null`。`seats_used` 仅统计**活跃**成员——暂停或移除某人会立即释放其席位。

---

## 直接添加团队成员

`POST /team/members`

直接将某人加入您的团队，无需发送邀请。

> **这不会发送任何电子邮件。** 不会通知任何人他们已被添加，如果他们还没有 <span data-t="appName">Your AI Connector</span> 登录账号，为他们创建的账户将**没有密码**，因此在重置密码之前他们无法登录。除非你有自己的方式通知对方并让他们登录，否则请使用 [发送邀请](#send-an-invitation)。

**请求字段**

| 字段 | 必填 | 说明 |
|---|---|---|
| `email` | 是 | 团队成员的电子邮件地址。 |
| `display_name` | 是 | 在应用中显示的成员姓名。 |
| `role` | 是 | `admin`、`editor` 或 `viewer`。 |
| `permission_overrides` | 否 | 针对角色默认设置的各区域例外情况。 |
| `contact_scope` | 否 | `all` 或 `assigned` — 请参阅 [限制成员可见范围](#limiting-what-a-member-can-see)。 |
| `contact_scope_unassigned` | 否 | 使用 `assigned` 时，允许他们查看尚未归属任何人的联系人。 |
| `contact_scope_axes` | 否 | 将其限制为指定的座席、渠道或部门。 |
| `sub_account_access` | 否 | 仅限代理机构 — 他们可以打开哪些客户子账户。 |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/team/members" \
  -H "Authorization: Bearer FIREBASE_ID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "sam@example.com",
    "display_name": "Sam Rivera",
    "role": "editor"
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/team/members", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${idToken}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    email: "sam@example.com",
    display_name: "Sam Rivera",
    role: "editor",
  }),
});
const { member_uid } = await res.json();
```

**响应** — `201 Created`

```json
{
  "success": true,
  "team_member_id": "owner_uid_123_uid_sam",
  "member_uid": "uid_sam",
  "message": "Team member created successfully."
}
```

| 状态 | 情况 |
|---|---|
| `400` | 缺少 `email`、`display_name` 或 `role`，角色不是这三种之一，或者你尝试添加自己。 |
| `403` | 你没有管理团队的权限，或者你尝试授予高于你自身权限的访问权。 |
| `409` | 该人员已经是你团队中的活跃成员。 |
| `429` | 你套餐中的团队席位已满。 |

添加之前被**暂停或移除**的人员会恢复其状态，而不是报错。

---

## 更新团队成员

`PATCH /team/members/{memberUid}`

更改成员的角色、权限、可见性、客户访问权限，或他们是否参与自动联系人分配。仅发送你想要更改的字段；任何你省略的字段将保持其当前值。

**请求字段**

| 字段 | 说明 |
|---|---|
| `role` | `admin`、`editor` 或 `viewer`。 |
| `permission_overrides` | 替换其整个覆盖列表。发送 `[]` 以使其恢复为纯角色默认设置。 |
| `status` | 仅接受 `active`，用于恢复已暂停的成员。要暂停某人，请使用 [暂停端点](#suspend-a-team-member)。 |
| `auto_assign_enabled` | `true` 或 `false`。 |
| `contact_scope` | `all` 或 `assigned`。 |
| `contact_scope_unassigned` | `true` 或 `false`。 |
| `contact_scope_axes` | 请参阅 [限制成员可见范围](#limiting-what-a-member-can-see)。 |
| `sub_account_access` | 仅限代理机构。 |

> **这是唯一一个 `null` 表示“清除”的端点。** 发送 `"contact_scope": null`、`"contact_scope_axes": null` 或 `"sub_account_access": null` 将完全移除该限制，使成员恢复到可见所有内容的状态。在创建和邀请时，`null` 仅表示“未提供”。

**cURL**

```bash
curl -X PATCH "https://api.youraiconnector.com/v1/team/members/uid_sam" \
  -H "Authorization: Bearer FIREBASE_ID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "admin",
    "permission_overrides": [{ "area": "billing", "level": "none" }]
  }'
```

**响应**

```json
{
  "success": true,
  "message": "Team member updated successfully."
}
```

| 状态 | 情况 |
|---|---|
| `400` | `status` 或 `auto_assign_enabled` 值无效，或者你尝试重新激活已被移除的成员（被移除的成员必须重新邀请）。 |
| `403` | 你没有权限，或者更改后的访问权限范围超出了你自身的权限。 |
| `404` | 无此团队成员。 |

---

## 暂停团队成员

`POST /team/members/{memberUid}/suspend`

暂停某人：他们保留团队中的位置但失去访问权限。当暂停是临时性时，请使用此功能而不是移除 — 使用 `PATCH /team/members/{memberUid}` 和 `{"status": "active"}` 将他们恢复。

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/team/members/uid_sam/suspend" \
  -H "Authorization: Bearer FIREBASE_ID_TOKEN"
```

**响应**

```json
{
  "success": true,
  "message": "Team member suspended successfully."
}
```

被暂停的成员会**释放其席位**，因此你可以邀请其他人代替他们。他们的访问权限会在其当前会话令牌下次刷新时终止，这可能需要长达一小时的时间 — 如果你需要立即生效，请改为移除他们。

| 状态 | 情况 |
|---|---|
| `400` | 你尝试暂停账户所有者，或尝试暂停已处于暂停或移除状态的成员。 |
| `403` | 他们的访问权限范围超出了你的权限。 |
| `404` | 无此团队成员。 |

---

## 移除团队成员

`DELETE /team/members/{memberUid}`

将某人从您的团队中移除并释放其席位。他们将被登出并失去对您账户的访问权限；他们自己的登录信息不受影响。

**cURL**

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/team/members/uid_sam" \
  -H "Authorization: Bearer FIREBASE_ID_TOKEN"
```

**响应**

```json
{
  "success": true,
  "message": "Team member removed successfully."
}
```

从您的角度来看，移除操作是永久性的：被移除的成员**无法**通过更新端点重新激活——如果您改变主意，请再次邀请他们。他们的电子邮件地址也会从您账户的通知列表中移除。

| 状态 | 原因 |
|---|---|
| `400` | 您尝试移除账户所有者。 |
| `403` | 他们的访问权限比您更广泛。 |
| `404` | 无此团队成员。 |

---

## 限制成员的可见范围

在 [添加](#add-a-team-member-directly)、[更新](#update-a-team-member) 和 [邀请](#send-an-invitation) 时可接受三个可选字段，用于决定成员可以看到账户的多少内容。它们是叠加生效的：如果成员受到多项限制，则受所有这些限制的共同约束。

**`contact_scope`** — `all`（默认值：所有联系人和对话）或 `assigned`（仅限分配给他们的内容）。使用 `assigned` 时，添加 `"contact_scope_unassigned": true` 还可以让他们看到尚未分配给任何人的联系人。

**`contact_scope_axes`** — 将他们限制在指定的坐席、渠道或部门：

| 字段 | 类型 | 描述 |
|---|---|---|
| `agents` | string[] | 坐席 ID。他们只能看到路由给这些坐席的聊天记录。最多 200 个。 |
| `channels` | string[] | 渠道名称 — `whatsapp`, `whatsapp_web`, `sms`, `instagram`, `instagram_private`, `messenger`, `facebook`, `chat_widget`, `telegram`, `line`, `viber`, `tiktok`, `imessage`, `email`, `linkedin`, `skool`, `custom`, `custom_channel`。最多 200 个。 |
| `departments` | string[] | 部门 ID（参见 [部门](#departments)）。他们只能看到归入这些部门下的线索。最多 200 个。 |
| `include_unrouted` | boolean | 设置为 `agents` 时，同时显示没有坐席处理的聊天记录。默认关闭。当 `agents` 为空时忽略此项。 |
| `include_undepartmented` | boolean | 设置为 `departments` 时，同时显示不属于任何部门的聊天记录。默认关闭。当 `departments` 为空时忽略此项。 |

保存时不会检查坐席和部门 ID——不存在的 ID 只是匹配不到任何内容，这会表现为空收件箱而不是错误。渠道名称**会**被检查：无法识别的名称会被 `400` 拒绝。


这三个字段均不能设置在账户所有者身上——该请求会被 `400` 拒绝。

---

## 列出邀请

`GET /team/invites`

按时间倒序排列您已发送的邀请，以便查看谁尚未接受邀请。

**查询参数**

| 参数 | 必需 | 描述 |
|---|---|---|
| `status` | 否 | 仅返回处于此状态的邀请 — `pending`、`accepted`、`declined`、`cancelled` 或 `expired`。 |

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/team/invites?status=pending" \
  -H "Authorization: Bearer FIREBASE_ID_TOKEN"
```

**响应**

```json
{
  "success": true,
  "invites": [
    {
      "id": "inv_abc123",
      "account_owner_uid": "owner_uid_123",
      "account_owner_display_name": "Acme Ltd",
      "invitee_email": "sam@example.com",
      "invitee_uid": null,
      "role": "editor",
      "permission_overrides": [],
      "status": "pending",
      "created_by": "owner_uid_123",
      "created_at": "2026-06-10T12:00:00.000Z",
      "expires_at": "2026-06-17T12:00:00.000Z",
      "responded_at": null
    }
  ]
}
```

邀请令牌永远不会被返回 — 它仅存在于已发送的电子邮件中。

---

## 发送邀请

`POST /team/invites`

通过电子邮件向某人发送加入团队的邀请。这是添加团队成员的常用方式：他们点击链接，以自己的身份登录并接受邀请。如果他们还没有 <span data-t="appName">Your AI Connector</span> 账户，系统会为他们创建一个，并引导他们通过电子邮件设置密码。

**请求字段**

| 字段 | 必需 | 描述 |
|---|---|---|
| `email` | 是 | 发送邀请的地址。 |
| `role` | 是 | `admin`、`editor` 或 `viewer`。 |
| `permission_overrides` | 否 | 各区域的例外权限，在他们接受邀请时立即应用。 |
| `contact_scope` | 否 | 在他们接受邀请时应用。 |
| `contact_scope_unassigned` | 否 | 在他们接受邀请时应用。 |
| `contact_scope_axes` | 否 | 在他们接受邀请时应用。 |
| `sub_account_access` | 否 | 仅限代理机构。在他们接受邀请时应用。 |

预先设置权限意味着您无需事后编辑成员信息 — 当他们接受邀请时，所有设置都会复制到他们的成员资格中。

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/team/invites" \
  -H "Authorization: Bearer FIREBASE_ID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "email": "sam@example.com", "role": "editor" }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/team/invites", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${idToken}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ email: "sam@example.com", role: "editor" }),
});
const { invite_id } = await res.json();
```

**响应** — `201 Created`

```json
{
  "success": true,
  "invite_id": "inv_abc123",
  "message": "Team invite sent successfully."
}
```

**需要规划的事项**

- **邀请在 7 天后过期。** 过期的邀请可以重新发送，重新发送后将开启新的 7 天有效期。
- **待处理的邀请会占用席位。** 与直接添加成员不同，此处的席位检查会计算活跃成员*加上*待处理的邀请，因此如果账户的所有席位已满，在发送电子邮件之前就会被拒绝。
- **每天 20 个邀请限制**，按账户计算，包含发送和重新发送。

| 状态 | 时间 |
|---|---|
| `400` | `email` 缺失或角色无效。 |
| `403` | 您没有管理团队的权限，或者您尝试授予高于您自身权限的访问权限。 |
| `409` | 该电子邮件的待处理邀请已存在，或者该人员已在您的团队中。 |
| `429` | 您套餐的团队席位已满，或者您已达到每天 20 个邀请的限制。`error` 消息会说明具体原因。 |

---

## 取消邀请

`DELETE /team/invites/{inviteId}`

在邀请被接受前撤销邀请。邮件中的链接将失效。

**cURL**

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/team/invites/inv_abc123" \
  -H "Authorization: Bearer FIREBASE_ID_TOKEN"
```

**响应**

```json
{
  "success": true,
  "message": "Team invite cancelled."
}
```

`pending` 和 `expired` 邀请均可被取消。如果邀请已被接受、拒绝或取消，则返回 `400`；如果邀请不属于您，则返回 `403`；如果 ID 未知，则返回 `404`。

---

## 重新发送邀请

`POST /team/invites/{inviteId}/resend`

再次发送邀请邮件——适用于邮件丢失或进入垃圾邮件文件夹的情况。适用于 `pending` 和 `expired` 邀请，并将过期时间重置为从现在起 7 天后。

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/team/invites/inv_abc123/resend" \
  -H "Authorization: Bearer FIREBASE_ID_TOKEN"
```

**响应**

```json
{
  "success": true,
  "message": "Team invite resent successfully."
}
```

新邮件包含一个新链接，且**旧链接依然有效**，因此如果用户稍后找到第一封邮件，也不会受阻。重新发送计入与发送相同的每日 20 次限制，并且重新激活*已过期*的邀请会重新检查您的席位——如果套餐已满，将返回 `429`。

---

## 接受邀请

`POST /team/invites/accept`

使用邀请邮件中的令牌接受邀请，将已登录的用户加入到该账户的团队中。

> **这是您个人身份的操作。** 请以您自己的身份登录——当您在他人账户内工作时，此操作会被明确拒绝，并返回 `403`。

**请求字段**

| 字段 | 必填 | 描述 |
|---|---|---|
| `invite_token` | 是 | 来自邀请邮件链接的令牌。 |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/team/invites/accept" \
  -H "Authorization: Bearer FIREBASE_ID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "invite_token": "1f4c…" }'
```

**响应**

```json
{
  "success": true,
  "team_member_id": "owner_uid_123_uid_sam",
  "account_owner_uid": "owner_uid_123",
  "message": "Team invite accepted successfully."
}
```

| 状态 | 情况 |
|---|---|
| `400` | `invite_token` 缺失，或邀请是发给您自己的账户的。 |
| `403` | 会话正在另一个账户内工作，或者邀请发送到的邮箱地址与您当前登录的邮箱地址不符。 |
| `404` | 邀请不存在或已被使用。 |
| `429` | 在邀请发出到您接受期间，账户席位已满。 |
| `504` | 邀请已过期。请要求发送者重新发送。 |

---

## 拒绝邀请

`POST /team/invites/decline`

使用邮件中的令牌拒绝邀请。与接受邀请一样，这是您个人身份的操作，当您在另一个账户内工作时，此操作会被拒绝。

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/team/invites/decline" \
  -H "Authorization: Bearer FIREBASE_ID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "invite_token": "1f4c…" }'
```

**响应**

```json
{
  "success": true,
  "message": "Team invite declined."
}
```

---

## 部门

**部门**是您团队中的一个命名组，例如：销售、客户支持、人力资源。它为潜在客户指定了一个所属团队，可以独立认领新的对话，并可用于限制成员的可见范围。

> **这四个端点需要 API 密钥。** 与本页面的其余部分不同，它们像 API 中的所有其他端点一样进行身份验证（请参阅[身份验证](authentication.md)）。已登录的会话也适用：读取需要 `contacts` 位于 `view`，创建、更改或删除需要 `team_management` 位于 `edit`。

**部门对象**

| 字段 | 类型 | 描述 |
|---|---|---|
| `id` | string | 部门的 ID。在 `contact_scope_axes.departments` 和下方的路径中使用它。 |
| `name` | string | 团队名称。最多 60 个字符，在账户内唯一。 |
| `color` | string \| null | 强调色，格式为 `#rrggbb` 或 `null`。 |
| `member_uids` | string[] | 该部门的团队成员。可能包含账户所有者。 |
| `auto_assign_enabled` | boolean | 归入此部门的潜在客户是否也会分配给其中的某个人。`false` 表示该部门通过共享队列工作。 |
| `routing_agents` | string[] | 由这些 AI 代理处理的新对话会自动归入此部门。为空表示没有代理规则。 |
| `routing_channels` | string[] | 这些渠道上的新对话会自动归入此处。为空表示没有渠道规则。 |
| `created_by` | string \| null | 创建者。 |

当同时设置了 `routing_agents` 和 `routing_channels` 时，对话必须**同时满足**这两个条件才能归入此处——这就是如何实现“支持代理，但仅限 WhatsApp”这种特定团队分配的方法。

一个账户最多可以拥有 **50** 个部门。

### 列出部门

`GET /team/departments`

```bash
curl "https://api.youraiconnector.com/v1/team/departments?apiKey=YOUR_API_KEY"
```

**响应**

```json
{
  "success": true,
  "departments": [
    {
      "id": "dep_abc123",
      "name": "Sales",
      "color": "#2f6fed",
      "member_uids": ["uid_alice", "uid_bob"],
      "auto_assign_enabled": true,
      "routing_agents": [],
      "routing_channels": ["whatsapp"],
      "created_by": "owner_uid_123"
    }
  ]
}
```

### 创建部门

`POST /team/departments`

**请求字段**

| 字段 | 必填 | 说明 |
|---|---|---|
| `name` | 是 | 最多 60 个字符。不得与现有部门重复。 |
| `color` | 否 | `#rrggbb` 十六进制，或 `null`。 |
| `member_uids` | 否 | 谁在其中。每个 UID 必须是账户所有者或**活跃**团队成员。 |
| `auto_assign_enabled` | 否 | 默认为 `true`。 |
| `routing_agents` | 否 | 新聊天会分配到的坐席 ID。 |
| `routing_channels` | 否 | 新聊天会分配到的渠道名称 — 与 `contact_scope_axes.channels` 使用相同的词汇。 |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/team/departments?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Sales",
    "color": "#2f6fed",
    "member_uids": ["uid_alice", "uid_bob"],
    "routing_channels": ["whatsapp"]
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/team/departments", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "Sales",
    color: "#2f6fed",
    member_uids: ["uid_alice", "uid_bob"],
    routing_channels: ["whatsapp"],
  }),
});
const { department } = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/team/departments",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "name": "Sales",
        "color": "#2f6fed",
        "member_uids": ["uid_alice", "uid_bob"],
        "routing_channels": ["whatsapp"],
    },
)
department = res.json()["department"]
```

**响应** — `201 Created`

```json
{
  "success": true,
  "department": {
    "id": "dep_abc123",
    "name": "Sales",
    "color": "#2f6fed",
    "member_uids": ["uid_alice", "uid_bob"],
    "auto_assign_enabled": true,
    "routing_agents": [],
    "routing_channels": ["whatsapp"],
    "created_by": "owner_uid_123"
  }
}
```

| 状态 | 情况 |
|---|---|
| `400` | `name` 缺失或过长，`color` 不是 `#rrggbb`，渠道名称无法识别，列出的 UID 不是此团队的活跃成员，或者您已经拥有 50 个部门。 |
| `409` | 同名部门已存在。 |

### 更新部门

`PATCH /team/departments/{departmentId}`

更改部门信息。仅会更改您发送的字段。

```bash
curl -X PATCH "https://api.youraiconnector.com/v1/team/departments/dep_abc123?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "member_uids": ["uid_alice"], "auto_assign_enabled": false }'
```

**响应**

```json
{
  "success": true,
  "department": {
    "id": "dep_abc123",
    "name": "Sales",
    "color": "#2f6fed",
    "member_uids": ["uid_alice"],
    "auto_assign_enabled": false,
    "routing_agents": [],
    "routing_channels": ["whatsapp"],
    "created_by": "owner_uid_123"
  }
}
```

发送未识别的字段将返回 `400`；未知的部门将返回 `404`；与另一个部门名称冲突将返回 `409`。

### 删除部门

`DELETE /team/departments/{departmentId}`

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/team/departments/dep_abc123?apiKey=YOUR_API_KEY"
```

**响应**

```json
{
  "success": true,
  "deleted": "dep_abc123"
}
```

> **拒绝删除某人受限访问的部门。** `400` 响应会列出可见性受限于该部门的成员名称，以便您可以先重新设置他们的范围。这是刻意为之的：静默地取消对他们的限制会将您的整个客户群暴露给他们，且没有任何迹象表明发生了这种情况。

归档在已删除部门下的联系人不会被重写——他们只是不再显示部门，下次您归档他们时，该部门信息将生效。

---

## 检查您自己的权限

`GET /team/permissions`

返回当前登录人员在当前操作的账户中被允许执行的操作。使用此接口隐藏成员无法使用的按钮，而不是让他们在遇到错误时才发现限制。

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/team/permissions" \
  -H "Authorization: Bearer FIREBASE_ID_TOKEN"
```

**响应 — 账户所有者**

```json
{
  "success": true,
  "role": "owner",
  "is_team_mode": false,
  "permissions": {
    "campaigns": "full",
    "contacts": "full",
    "messages": "full",
    "appointments": "full",
    "settings": "full",
    "billing": "full",
    "team_management": "full",
    "analytics": "full",
    "phone_numbers": "full",
    "integrations": "full",
    "faqs": "full",
    "daily_summaries": "full"
  }
}
```

**响应 — 在账户内工作的团队成员**

```json
{
  "success": true,
  "role": "editor",
  "is_team_mode": true,
  "permissions": { "campaigns": "edit", "billing": "none", "…": "…" },
  "member": {
    "uid": "uid_sam",
    "email": "sam@example.com",
    "display_name": "Sam Rivera",
    "account_owner_uid": "owner_uid_123"
  }
}
```

当登录人员是账户所有者时，`role` 为 `owner`；否则为他们的团队角色。`member` 仅在团队模式下存在，并携带 `contact_scope`、`contact_scope_unassigned` 和 `contact_scope_axes`（当他们的成员资格包含这些权限时）。

---

## 会话令牌

五个端点会生成用于在账户之间切换的一次性登录令牌。它们的响应方式相同：

```json
{
  "success": true,
  "customToken": "eyJhbGciOi…"
}
```

该令牌用于与 Firebase 客户端 SDK 交换会话。**它不是 API 密钥，不能作为 API 密钥发送**，这就是为什么这些端点仅在第一方应用程序内有用。

| 端点 | 功能 | 正文 |
|---|---|---|
| `POST /team/tokens/team-member` | 允许团队成员开始在他们所属的账户内工作。 | `account_owner_uid` (必需) |
| `POST /team/tokens/return-from-team` | 将他们带回他们自己的账户。 | — |
| `POST /team/tokens/assist` | 允许 <span data-t="appName">Your AI Connector</span> 员工打开客户账户以提供帮助。仅限员工。 | `customerUid` |
| `POST /team/tokens/return-to-admin` | 结束协助会话并将员工返回到他们自己的账户。 | — |
| `POST /team/tokens/agency-assist` | 允许代理机构打开其客户子账户之一——或者在不带参数调用时，返回到代理机构账户。 | `subAccountUid` (可选) |

当会话无权执行此操作时，每个接口都会返回 `403`：例如不是该账户的成员、不是员工、该子账户不属于您的代理机构或未授权给您，或者会话当前所处的模式与端点要求的模式不符。

---

## 分配平台角色

`POST /team/users/{targetUid}/role`

设置用户的**平台**角色 — `User`、`Dev`、`Support` 或 `Agency`。这并非团队成员身份：它决定了某人拥有何种类型的 <span data-t="appName">Your AI Connector</span> 账户。

此端点仅限 <span data-t="appName">Your AI Connector</span> 员工使用，且最后一名 `Dev` 不能被降级。此处列出仅为完整性考虑；它不属于管理您自己团队的范畴。

```json
{
  "success": true,
  "targetUid": "uid_sam",
  "role": "Agency",
  "claimUpdated": true
}
```

| 状态 | 情况 |
|---|---|
| `400` | `role` 缺失或不是这四种角色之一，或者此操作会移除最后一名 `Dev`。 |
| `403` | 您不是员工，或者会话正在另一个账户内工作。 |
| `404` | 无此用户。 |

---

## 团队 API 错误

团队端点返回标准的错误封装，并始终在 HTTP 状态码之外包含 `error_code`：

```json
{
  "success": false,
  "error_code": 403,
  "error": "Cannot grant \"full\" access to \"billing\" — exceeds your own permissions."
}
```

| 状态 | 在团队端点上发生时 |
|---|---|
| `400` | 必填字段缺失或无效，或者当前状态下不允许执行此操作（例如重新激活已移除的成员、暂停所有者、删除某人受限的部门）。 |
| `401` | 您向需要登录用户的端点发送了 API 密钥 — 请参阅 [身份验证](#authentication-these-endpoints-need-a-signed-in-person)。 |
| `403` | 您没有 `team_management` 权限，更改超出了您的访问范围，或者在另一个账户内工作时拒绝执行此操作。 |
| `404` | 无此成员、邀请、部门或用户。 |
| `409` | 已是团队成员、已存在待处理的邀请，或已存在同名部门。 |
| `429` | 团队席位已满、达到每日 20 次邀请的限制，或您触及了 API 速率限制。 |
| `504` | 您尝试接受的邀请已过期。 |

每个端点都可能返回的共享代码 — `429`（速率限制）和 `500` — 及其重试指南列在 [错误与分页](errors-and-pagination.md) 中。

---

## 相关内容

- [团队管理](../settings/team-management.md) — 仪表板中的相同功能，附带截图。
- [身份验证](authentication.md) — 如何发送 Firebase ID 令牌而非 API 密钥。
- [联系人 API](contacts.md) — 成员可见性限制所适用的联系人。

