
# チーム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)を参照）。サーバー間統合ではチームメンバーを管理できません。アプリの外部からこれらのトークンを作成する方法はないためです。

> **例外：** 4つの[部門](#departments)エンドポイントは通常のAPIエンドポイントです。これらは、APIの他の部分と同様にAPIキーを受け入れるほか、サインインしたセッションでも利用可能です。

このページのすべてのレスポンスは、通常のエンベロープに従います。トップレベルに `success: true` とエンドポイントのフィールドが含まれるか、エラーが発生した場合は `success: false` に `error` と `error_code` が含まれます。

---

## ロールと権限

すべてのチームメンバーには1つの**ロール**があり、アプリ内の12の領域に対するデフォルトのアクセス権が設定されます。その後、個別の領域ごとに権限を上書きできます。

| ロール | 値 | 概要 |
|---|---|---|
| 管理者 | `admin` | オーナーの請求関連アクションを除くすべて。 |
| エディター | `editor` | 作成および変更が可能。アプリ内では**エージェント**と表示されます。 |
| 閲覧者 | `viewer` | 読み取り専用。 |

各領域は、`none`（非表示）、`view`（読み取り専用）、`edit`（作成および変更）、`full`（削除を含む）の4つのレベルのいずれかに設定されます。

| 領域 | 管理者 | エディター | 閲覧者 |
|---|---|---|---|
| `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`

名簿とプランのシート数（座席数）を返します。これにより、「5席中3席使用」といった表示が可能になり、招待が拒否されるタイミングを把握できます。

**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` が不足している、ロールが3つのいずれでもない、または自分自身を追加しようとした場合。 |
| `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."
}
```

停止されたメンバーは **シートを解放する** ため、代わりに他のメンバーを招待できます。アクセス権は現在のセッションのトークンが次に更新されるときに終了します（最大1時間かかる場合があります）。即座にアクセスを終了させる必要がある場合は、削除を行ってください。

| ステータス | 条件 |
|---|---|
| `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)の各操作で受け入れられる3つのオプションフィールドにより、その人物がアカウントのどの範囲まで閲覧できるかを決定します。これらは累積されます。複数の制限が適用されているメンバーは、そのすべてによって制限されます。

**`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は保存時にチェックされません。存在しないIDは単に何も一致しないだけとなり、エラーではなく空の受信トレイとして表示されます。チャネル名は**チェックされます**。認識されないチャネル名は `400` で拒否されます。


これら3つの設定はいずれもアカウント所有者には適用できません。そのリクエストは `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日間の有効期限が始まります。
- **保留中の招待はシートを占有します。** メンバーを直接追加する場合とは異なり、ここでのシートチェックは、アクティブなメンバー数に保留中の招待数を加算してカウントされます。そのため、すべてのシートが埋まっているアカウントでは、メールが送信される前に拒否されます。
- **1日あたり20件の招待制限があります。** これはアカウントごとに、送信と再送を合計してカウントされます。

| ステータス | 時期 |
|---|---|
| `400` | `email` が欠落しているか、ロールが無効です。 |
| `403` | チームを管理する権限がないか、自分自身の権限を超えるアクセス権を付与しようとしました。 |
| `409` | そのメールアドレスに対する保留中の招待が既に存在するか、その人物は既にチームに所属しています。 |
| `429` | プランのチームシートがいっぱいであるか、1日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."
}
```

新しいメールには新しいリンクが含まれますが、**古いリンクも引き続き機能する**ため、後から最初のメールを見つけたユーザーが困ることはありません。再送も送信と同様に1日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."
}
```

---

## 部門

**部門**とは、営業、カスタマーサポート、人事など、チーム内のグループに名前を付けたものです。部門を設定すると、リードに担当チームを割り当てたり、部門単位で新しい会話を取得したりできるほか、メンバーが閲覧できる範囲を制限することも可能です。

> **これら4つのエンドポイントはAPIキーを使用します。** このページの他のエンドポイントとは異なり、APIの他のすべてのエンドポイントと同様の認証方法（[認証](authentication.md)を参照）を使用します。サインインしたセッションでも機能します。読み取りには `view` での `contacts` が必要であり、作成、変更、削除には `edit` での `team_management` が必要です。

**部門オブジェクト**

| フィールド | 型 | 説明 |
|---|---|---|
| `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のみ」といったチームへの割り当てが可能になります。

1つのアカウントにつき最大 **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` 16進数、または `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` が含まれている場合にそれらを保持します。

---

## セッショントークン

5つのエンドポイントが、アカウントを切り替えるためのワンタイムサインイントークンを発行します。これらはすべて同じ方法で応答します。

```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>スタッフに制限されており、最後の1人の`Dev`を降格させることはできません。完全を期すために記載していますが、これは自身のチーム管理の一部ではありません。

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

| ステータス | 発生条件 |
|---|---|
| `400` | `role`が欠落しているか、4つのロールのいずれでもない場合、またはこれにより最後の`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` | チームのシートがいっぱいである、1日20件の招待制限に達した、またはAPIレート制限に達した場合。 |
| `504` | 承諾しようとした招待の有効期限が切れています。 |

すべてのエンドポイントが返す可能性のある共通コード（`429`（レート制限）および`500`）については、再試行のガイダンスとともに[エラーとページネーション](errors-and-pagination.md)に記載されています。

---

## 関連情報

- [チーム管理](../settings/team-management.md) — ダッシュボードでの同じ機能（スクリーンショット付き）。
- [認証](authentication.md) — APIキーの代わりにFirebase IDトークンを送信する方法。
- [連絡先API](contacts.md) — メンバーの可視性制限が適用される連絡先。

