
# Team-API

Ditt team är alla som arbetar i ditt konto förutom du själv — administratörer, agenter och läsbehöriga användare — plus de inbjudningar du har skickat och de avdelningar du har organiserat dem i. Team-API:et är den programmatiska versionen av **Inställningar → Team**: lägg till och ta bort personer, ställ in vad var och en kan se och göra, skicka och påminna om inbjudningar samt hantera avdelningar.

Alla slutpunkter nedan är relativa till bas-URL:en `https://api.youraiconnector.com/v1`. För dashboard-versionen av allt på denna sida, se [Teamhantering](../settings/team-management.md).

---

## Autentisering: dessa slutpunkter kräver en inloggad person

**Detta är den enda delen av API:et som en API-nyckel inte kan använda.** Varje `/team`-slutpunkt förutom [avdelnings](#departments)-slutpunkterna måste anropas med en **Firebase ID-token** från en inloggad session:

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

Skicka en API-nyckel istället så avvisas begäran med ett `401`:

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

Anledningen är att dessa slutpunkter fattar beslut baserat på **vem som är inloggad**: din roll, taket för vad du får bevilja någon annan, och om du för närvarande arbetar i ett annat konto. En API-nyckel är en integration, inte en person, så det finns ingen som dessa regler kan tillämpas på.

I praktiken innebär det att Team-API:et är till för en förstapartsapp med en inloggad <span data-t="appName">Your AI Connector</span>-användare (se [Autentisering → Firebase ID-token](authentication.md#4-firebase-id-token-first-party-only)). En server-till-server-integration kan inte hantera teammedlemmar — det finns inget sätt att skapa en av dessa tokens utanför appen.

> **Undantaget:** de fyra [avdelnings](#departments)-slutpunkterna är vanliga API-slutpunkter. De accepterar din API-nyckel precis som resten av API:et, såväl som en inloggad session.

Varje svar på denna sida följer det vanliga kuvertet: `success: true` plus slutpunktens fält på toppnivå, eller `success: false` med `error` och `error_code` när något går fel.

---

## Roller och behörigheter

Varje teammedlem har en **roll**, som anger deras standardåtkomst över 12 områden i appen. Du kan sedan åsidosätta enskilda områden.

| Roll | Värde | Sammanfattning |
|---|---|---|
| Admin | `admin` | Allt utom ägarens faktureringsrelaterade åtgärder. |
| Editor | `editor` | Kan skapa och ändra saker. Visas som **Agent** i appen. |
| Viewer | `viewer` | Skrivskyddad. |

Varje område är inställt på en av fyra nivåer: `none` (dolt), `view` (skrivskyddat), `edit` (skapa och ändra), `full` (inklusive borttagning).

| Område | Admin | Editor | Viewer |
|---|---|---|---|
| `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 |

För att avvika från rollens standardvärden, skicka `permission_overrides` — en array av `{ "area": ..., "level": ... }`-objekt. Varje post ersätter rollens standardvärde för just det området; allt du inte listar behåller rollens standardvärde.

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

**Vem kan anropa dessa slutpunkter**

- **Kontoinnehavaren** kan alltid göra allt.
- En teammedlem behöver `team_management` på `view` för att läsa medlemslistan och inbjudningslistan, och på `edit` för att lägga till, ändra, inaktivera, ta bort, bjuda in, avbryta eller skicka om. Administratörer har `edit` som standard; redigerare och läsare har `none`, så som standard är det endast administratörer som kan hantera teamet.
- **Ingen kan bevilja högre åtkomst än sin egen.** Om du försöker ge någon en nivå som du inte själv innehar — eller redigera, inaktivera eller ta bort någon vars åtkomst redan är bredare än din — nekas begäran med `403` och ett meddelande som anger området.

---

## Teammedlemsobjektet

`GET /team/members` returnerar ett av dessa per medlem:

| Fält | Typ | Beskrivning |
|---|---|---|
| `member_uid` | string | Medlemmens eget användar-ID. Detta är `{memberUid}` i sökvägarna nedan. |
| `account_owner_uid` | string | Kontot de är medlem i. |
| `member_email` | string | Deras e-postadress. |
| `member_display_name` | string | Namnet som visas för dem i appen. |
| `role` | string | `admin`, `editor` eller `viewer`. |
| `permission_overrides` | array | Deras undantag per område. `[]` när de enbart använder rollstandardvärden. |
| `status` | string | `active` eller `suspended`. |
| `auto_assign_enabled` | boolean \| null | Huruvida nya kontakter kan tilldelas dem automatiskt. `null` betyder att det aldrig ändrats, vilket fungerar som `true`. |
| `created_by` | string | Vem som lade till dem. |
| `created_at` | string \| null | ISO 8601-tidsstämpel. |
| `updated_at` | string \| null | ISO 8601-tidsstämpel. |

Borttagna medlemmar returneras inte — listan innehåller endast aktiva och inaktiverade medlemmar.

> **Synlighetsbegränsningar är endast skrivbara här.** `contact_scope`, `contact_scope_axes` och `sub_account_access` (se [Begränsa vad en medlem kan se](#limiting-what-a-member-can-see)) kan ställas in vid skapande, uppdatering och inbjudan, men denna slutpunkt returnerar dem inte.

---

## Lista teammedlemmar

`GET /team/members`

Returnerar medlemslistan plus din plans platsantal, så att du kan visa "3 av 5 platser" och veta när en inbjudan är på väg att nekas.

**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()
```

**Svar**

```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` är `null` när din plan inte har något platsantal. `seats_used` räknar endast **aktiva** medlemmar — att inaktivera eller ta bort någon frigör deras plats omedelbart.

---

## Lägg till en teammedlem direkt

`POST /team/members`

Lägger till någon i ditt team direkt, utan en inbjudan.

> **Detta skickar inget e-postmeddelande.** Ingen meddelas om att de har lagts till, och om de inte redan hade en <span data-t="appName">Your AI Connector</span>-inloggning har kontot som skapats för dem **inget lösenord**, så de kan inte logga in förrän de återställer det. Använd [Skicka en inbjudan](#send-an-invitation) såvida du inte har ett eget sätt att informera personen och hjälpa dem att logga in.

**Begäransfält**

| Fält | Obligatoriskt | Beskrivning |
|---|---|---|
| `email` | Ja | Lagmedlemmens e-postadress. |
| `display_name` | Ja | Namnet som visas för dem i appen. |
| `role` | Ja | `admin`, `editor` eller `viewer`. |
| `permission_overrides` | Nej | Undantag per område från rollens standardinställningar. |
| `contact_scope` | Nej | `all` eller `assigned` — se [Begränsa vad en medlem kan se](#limiting-what-a-member-can-see). |
| `contact_scope_unassigned` | Nej | Med `assigned`, låt dem även se kontakter som ingen äger ännu. |
| `contact_scope_axes` | Nej | Begränsa dem till namngivna agenter, kanaler eller avdelningar. |
| `sub_account_access` | Nej | Endast för byråer — vilka klientunderkonton de får öppna. |

**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();
```

**Svar** — `201 Created`

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

| Status | När |
|---|---|
| `400` | `email`, `display_name` eller `role` saknas, rollen är inte en av de tre, eller så försökte du lägga till dig själv. |
| `403` | Du har inte behörighet att hantera teamet, eller så försökte du bevilja åtkomst utöver din egen. |
| `409` | Personen är redan en aktiv medlem i ditt team. |
| `429` | Ditt abonnemangs teamplatser är fulla. |

Att lägga till någon som tidigare var **avstängd eller borttagen** återaktiverar dem istället för att misslyckas.

---

## Uppdatera en teammedlem

`PATCH /team/members/{memberUid}`

Ändrar en medlems roll, behörigheter, synlighet, klientåtkomst eller om de deltar i automatisk kontakttilldelning. Skicka endast de fält du vill ändra; allt du utelämnar behåller sitt nuvarande värde.

**Begäransfält**

| Fält | Beskrivning |
|---|---|
| `role` | `admin`, `editor` eller `viewer`. |
| `permission_overrides` | Ersätter hela deras lista med undantag. Skicka `[]` för att återställa dem till enbart rollens standardinställningar. |
| `status` | Endast `active` accepteras för att återaktivera en avstängd medlem. För att stänga av någon, använd [avstängnings-endpointen](#suspend-a-team-member). |
| `auto_assign_enabled` | `true` eller `false`. |
| `contact_scope` | `all` eller `assigned`. |
| `contact_scope_unassigned` | `true` eller `false`. |
| `contact_scope_axes` | Se [Begränsa vad en medlem kan se](#limiting-what-a-member-can-see). |
| `sub_account_access` | Endast för byråer. |

> **Detta är den enda endpointen där `null` betyder "rensa".** Att skicka `"contact_scope": null`, `"contact_scope_axes": null` eller `"sub_account_access": null` tar bort den begränsningen helt och återställer medlemmen till att se allt. Vid skapande och inbjudan betyder `null` helt enkelt "ej angivet".

**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" }]
  }'
```

**Svar**

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

| Status | När |
|---|---|
| `400` | Ett ogiltigt `status`- eller `auto_assign_enabled`-värde, eller så försökte du återaktivera en medlem som tagits bort (borttagna medlemmar måste bjudas in på nytt). |
| `403` | Du har inte behörighet, eller så skulle ändringen redigera eller skapa åtkomst som är bredare än din egen. |
| `404` | Ingen sådan teammedlem. |

---

## Stäng av en teammedlem

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

Stänger av någon: de behåller sin plats i teamet men förlorar åtkomst. Använd detta istället för att ta bort när pausen är tillfällig — ta tillbaka dem med `PATCH /team/members/{memberUid}` och `{"status": "active"}`.

**cURL**

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

**Svar**

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

En avstängd medlem **frigör sin plats**, så att du kan bjuda in någon annan i deras ställe. Deras åtkomst upphör när deras nuvarande sessionstoken nästa gång uppdateras, vilket kan ta upp till en timme — ta bort dem istället om du behöver att det sker omedelbart.

| Status | När |
|---|---|
| `400` | Du försökte stänga av kontoägaren, eller en medlem som redan är avstängd eller borttagen. |
| `403` | Deras åtkomst är bredare än din. |
| `404` | Ingen sådan teammedlem. |

---

## Ta bort en teammedlem

`DELETE /team/members/{memberUid}`

Tar bort en person från ditt team och frigör deras plats. De loggas ut och förlorar åtkomst till ditt konto; deras egen inloggning förblir orörd.

**cURL**

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

**Svar**

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

Borttagningen är permanent från din sida: en borttagen medlem **kan inte återaktiveras** via uppdateringsslutpunkten — bjud in dem igen om du ändrar dig. Deras e-postadress tas även bort från kontots aviseringslista.

| Status | När |
|---|---|
| `400` | Du försökte ta bort kontots ägare. |
| `403` | Deras åtkomst är bredare än din. |
| `404` | Ingen sådan teammedlem finns. |

---

## Begränsa vad en medlem kan se

Tre valfria fält, som accepteras vid [lägg till](#add-a-team-member-directly), [uppdatera](#update-a-team-member) och [bjuda in](#send-an-invitation), avgör hur mycket av kontot en person ser. De staplas: en medlem som är begränsad på mer än ett sätt begränsas av alla.

**`contact_scope`** — `all` (standard: alla kontakter och konversationer) eller `assigned` (endast de som tilldelats dem). Med `assigned`, lägg till `"contact_scope_unassigned": true` för att även låta dem se kontakter som ingen äger ännu.

**`contact_scope_axes`** — begränsar dem till namngivna agenter, kanaler eller avdelningar:

| Fält | Typ | Beskrivning |
|---|---|---|
| `agents` | string[] | Agent-ID:n. De ser endast chattar som dirigeras till en av dessa agenter. Max 200. |
| `channels` | string[] | Kanalnamn — `whatsapp`, `whatsapp_web`, `sms`, `instagram`, `instagram_private`, `messenger`, `facebook`, `chat_widget`, `telegram`, `line`, `viber`, `tiktok`, `imessage`, `email`, `linkedin`, `skool`, `custom`, `custom_channel`. Max 200. |
| `departments` | string[] | Avdelnings-ID:n (se [Avdelningar](#departments)). De ser endast leads som arkiverats under dessa. Max 200. |
| `include_unrouted` | boolean | Med `agents` aktiverat, visas även chattar som ingen agent hanterar. Avstängd som standard. Ignoreras när `agents` är tomt. |
| `include_undepartmented` | boolean | Med `departments` aktiverat, visas även chattar som inte tillhör någon avdelning. Avstängd som standard. Ignoreras när `departments` är tomt. |

Agent- och avdelnings-ID:n kontrolleras inte när du sparar dem — ett ID som inte existerar matchar helt enkelt ingenting, vilket visas som en tom inkorg istället för ett fel. Kanalnamn **kontrolleras**: ett okänt namn avvisas med `400`.


Inget av dessa tre kan ställas in på kontots ägare — den begäran nekas med `400`.

---

## Lista inbjudningar

`GET /team/invites`

De inbjudningar du har skickat, sorterade med de nyaste först, så att du kan se vem som ännu inte har accepterat.

**Frågeparametrar**

| Parameter | Krävs | Beskrivning |
|---|---|---|
| `status` | Nej | Returnera endast inbjudningar i detta tillstånd — `pending`, `accepted`, `declined`, `cancelled` eller `expired`. |

**cURL**

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

**Svar**

```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
    }
  ]
}
```

Inbjudningstoken returneras aldrig — den finns bara i e-postmeddelandet som skickades.

---

## Skicka en inbjudan

`POST /team/invites`

Skickar en inbjudan via e-post till någon att gå med i ditt team. Detta är det vanliga sättet att lägga till en teammedlem: de klickar på länken, loggar in som sig själva och accepterar. Om de inte har ett <span data-t="appName">Your AI Connector</span>-konto ännu skapas ett åt dem, och e-postmeddelandet guidar dem genom att ställa in ett lösenord.

**Begäransfält**

| Fält | Krävs | Beskrivning |
|---|---|---|
| `email` | Ja | Vart inbjudan ska skickas. |
| `role` | Ja | `admin`, `editor` eller `viewer`. |
| `permission_overrides` | Nej | Undantag per område, tillämpas i samma ögonblick som de accepterar. |
| `contact_scope` | Nej | Tillämpas när de accepterar. |
| `contact_scope_unassigned` | Nej | Tillämpas när de accepterar. |
| `contact_scope_axes` | Nej | Tillämpas när de accepterar. |
| `sub_account_access` | Nej | Endast för byråer. Tillämpas när de accepterar. |

Genom att ställa in behörigheter i förväg behöver du inte redigera medlemmen efteråt — allt kopieras till deras medlemskap när de accepterar.

**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();
```

**Svar** — `201 Created`

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

**Saker att planera för**

- **Inbjudningar går ut efter 7 dagar.** En utgången inbjudan kan skickas på nytt, vilket startar en ny 7-dagarsperiod.
- **Väntande inbjudningar upptar en plats.** Till skillnad från att lägga till en medlem direkt, räknar platskontrollen här aktiva medlemmar *plus* väntande inbjudningar, så ett konto där alla platser är upptagna nekas innan e-postmeddelandet skickas.
- **20 inbjudningar per dag**, räknat per konto för både utskick och återskick.

| Status | När |
|---|---|
| `400` | `email` saknas eller rollen är ogiltig. |
| `403` | Du har inte behörighet att hantera teamet, eller så försökte du ge åtkomst utöver din egen nivå. |
| `409` | En väntande inbjudan för den e-postadressen finns redan, eller så är personen redan med i ditt team. |
| `429` | Ditt abonnemangs teamplatser är fulla, eller så har du nått gränsen på 20 inbjudningar per dag. Meddelandet `error` anger vilket. |

---

## Avbryt en inbjudan

`DELETE /team/invites/{inviteId}`

Drar tillbaka en inbjudan innan den har accepterats. Länken i e-postmeddelandet slutar fungera.

**cURL**

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

**Svar**

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

Både `pending`- och `expired`-inbjudningar kan avbrytas. En inbjudan som redan har accepterats, avböjts eller avbrutits returnerar `400`; en som inte är din returnerar `403`; ett okänt ID returnerar `404`.

---

## Skicka inbjudan på nytt

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

Skickar inbjudningsmeddelandet igen — för när det missades eller hamnade i skräpposten. Fungerar på `pending`- och `expired`-inbjudningar och återställer utgångstiden till 7 dagar från nu.

**cURL**

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

**Svar**

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

Det nya e-postmeddelandet innehåller en ny länk, och **den gamla länken fortsätter också att fungera**, så en person som hittar det första e-postmeddelandet senare blir inte stående utan åtkomst. Att skicka på nytt räknas mot samma gräns på 20 per dag som att skicka, och att återaktivera en *utgången* inbjudan kontrollerar dina platser på nytt — en full plan nekas med `429`.

---

## Acceptera en inbjudan

`POST /team/invites/accept`

Accepterar en inbjudan med token från inbjudningsmeddelandet och lägger till den inloggade personen i det kontots team.

> **Detta är en handling som utförs av din egen identitet.** Logga in som dig själv — det nekas avsiktligt med `403` medan du arbetar inuti någon annans konto.

**Begäransfält**

| Fält | Krävs | Beskrivning |
|---|---|---|
| `invite_token` | Ja | Token från länken i inbjudningsmeddelandet. |

**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…" }'
```

**Svar**

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

| Status | När |
|---|---|
| `400` | `invite_token` saknas, eller så är inbjudan för ditt eget konto. |
| `403` | Sessionen arbetar inuti ett annat konto, eller så skickades inbjudan till en annan e-postadress än den du är inloggad med. |
| `404` | Inbjudan finns inte eller har redan använts. |
| `429` | Kontots platser fylldes mellan inbjudan och ditt godkännande. |
| `504` | Inbjudan har gått ut. Be avsändaren att skicka den på nytt. |

---

## Avböj en inbjudan

`POST /team/invites/decline`

Avböjer en inbjudan med token från e-postmeddelandet. Precis som vid godkännande är detta en handling som utförs av din egen identitet och nekas medan du arbetar inuti ett annat konto.

**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…" }'
```

**Svar**

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

---

## Avdelningar

En **avdelning** är en namngiven grupp i ditt team — Försäljning, Kundsupport, HR. Den ger en lead ett ägande team, kan själv ta hand om nya konversationer och kan användas för att begränsa vad en medlem ser.

> **Dessa fyra slutpunkter kräver en API-nyckel.** Till skillnad från resten av den här sidan autentiseras de som alla andra slutpunkter i API:et (se [Autentisering](authentication.md)). En inloggad session fungerar också: läsning kräver `contacts` vid `view`, och att skapa, ändra eller ta bort kräver `team_management` vid `edit`.

**Avdelningsobjektet**

| Fält | Typ | Beskrivning |
|---|---|---|
| `id` | string | Avdelningens ID. Använd det i `contact_scope_axes.departments` och i sökvägarna nedan. |
| `name` | string | Vad teamet heter. Upp till 60 tecken, unikt för kontot. |
| `color` | string \| null | Accentfärg som `#rrggbb`, eller `null`. |
| `member_uids` | string[] | Teammedlemmarna i denna avdelning. Kan inkludera kontoägaren. |
| `auto_assign_enabled` | boolean | Om en lead som arkiveras under denna avdelning också tilldelas någon i den. `false` innebär att avdelningen arbetar från en delad kö. |
| `routing_agents` | string[] | Nya konversationer som hanteras av dessa AI-agenter arkiveras automatiskt under denna avdelning. Tomt innebär ingen agentregel. |
| `routing_channels` | string[] | Nya konversationer i dessa kanaler arkiveras här automatiskt. Tomt innebär ingen kanalregel. |
| `created_by` | string \| null | Vem som skapade den. |

När både `routing_agents` och `routing_channels` är inställda måste en konversation matcha **båda** för att arkiveras här — det är så du ger ett team "supportagenten, men bara på WhatsApp".

Ett konto kan ha upp till **50** avdelningar.

### Lista avdelningar

`GET /team/departments`

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

**Svar**

```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"
    }
  ]
}
```

### Skapa en avdelning

`POST /team/departments`

**Begäransfält**

| Fält | Krävs | Beskrivning |
|---|---|---|
| `name` | Ja | Upp till 60 tecken. Får inte matcha en befintlig avdelning. |
| `color` | Nej | `#rrggbb` hex, eller `null`. |
| `member_uids` | Nej | Vilka som ingår. Varje UID måste vara kontoägaren eller en **aktiv** teammedlem. |
| `auto_assign_enabled` | Nej | Standardvärdet är `true`. |
| `routing_agents` | Nej | Agent-ID:n vars nya chattar hamnar här. |
| `routing_channels` | Nej | Kanalnamn vars nya chattar hamnar här — samma vokabulär som `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"]
```

**Svar** — `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"
  }
}
```

| Status | När |
|---|---|
| `400` | `name` saknas eller är för lång, `color` är inte `#rrggbb`, ett kanalnamn känns inte igen, ett listat UID är inte en aktiv medlem i detta team, eller så har du redan 50 avdelningar. |
| `409` | En avdelning med det namnet finns redan. |

### Uppdatera en avdelning

`PATCH /team/departments/{departmentId}`

Ändrar en avdelning. Endast de fält du skickar ändras.

```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 }'
```

**Svar**

```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"
  }
}
```

Om inga kända fält skickas returneras `400`; en okänd avdelning returnerar `404`; ett namn som krockar med en annan avdelning returnerar `409`.

### Ta bort en avdelning

`DELETE /team/departments/{departmentId}`

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

**Svar**

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

> **Det går inte att ta bort en avdelning som någon är begränsad till.** Svaret `400` anger de medlemmar vars synlighet är begränsad till den, så att du kan ändra deras omfattning först. Detta är avsiktligt: att tyst ta bort begränsningen skulle ge dem tillgång till hela din kundbas utan att det märks.

Kontakter som sorterats under en borttagen avdelning skrivs inte om — de slutar helt enkelt visa en avdelning, och nästa gång du sorterar dem kommer det att fungera.

---

## Kontrollera dina egna behörigheter

`GET /team/permissions`

Returnerar vad den inloggade personen har tillåtelse att göra i det konto de för närvarande arbetar i. Använd detta för att dölja knappar som en medlem inte kan använda, istället för att låta dem upptäcka begränsningen genom ett felmeddelande.

**cURL**

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

**Svar — kontoinnehavaren**

```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"
  }
}
```

**Svar — en teammedlem som arbetar i ett konto**

```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` är `owner` när den inloggade personen är kontoinnehavaren; annars är det deras teamroll. `member` finns endast i teamläge och innehåller `contact_scope`, `contact_scope_unassigned` och `contact_scope_axes` när deras medlemskap har dessa.

---

## Sessions-tokens

Fem slutpunkter skapar en engångs-inloggningstoken för att växla mellan konton. De svarar alla på samma sätt:

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

Token byts ut mot en session med Firebase-klientens SDK. **Det är inte en API-nyckel och kan inte skickas som en sådan**, vilket är anledningen till att dessa slutpunkter endast är användbara i en förstapartsapp.

| Slutpunkt | Vad den gör | Brödtext |
|---|---|---|
| `POST /team/tokens/team-member` | Låter en teammedlem börja arbeta i ett konto de tillhör. | `account_owner_uid` (obligatorisk) |
| `POST /team/tokens/return-from-team` | Tar dem tillbaka till deras eget konto. | — |
| `POST /team/tokens/assist` | Låter <span data-t="appName">Your AI Connector</span>-personal öppna en kunds konto för att hjälpa till. Endast för personal. | `customerUid` |
| `POST /team/tokens/return-to-admin` | Avslutar en assistsession och returnerar personalen till deras eget konto. | — |
| `POST /team/tokens/agency-assist` | Låter en byrå öppna ett av sina klientunderkonton — eller, om den anropas utan ett, återgå till byråkontot. | `subAccountUid` (valfri) |

Var och en nekar med `403` när sessionen inte har rätt till det: inte medlem i det kontot, inte personal, underkontot tillhör inte din byrå eller har inte beviljats dig, eller så är sessionen för närvarande inte i det läge som slutpunkten kräver.

---

## Tilldela en plattformsroll

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

Ställer in en användares **plattformsroll** — `User`, `Dev`, `Support` eller `Agency`. Detta är inte ett teammedlemskap: det är vilken typ av <span data-t="appName">Your AI Connector</span>-konto någon har.

Denna slutpunkt är begränsad till <span data-t="appName">Your AI Connector</span>-personal, och den sista kvarvarande `Dev` kan inte nedgraderas. Listad för fullständighet; den är inte en del av att hantera ditt eget team.

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

| Status | När |
|---|---|
| `400` | `role` saknas eller är inte en av de fyra, eller detta skulle ta bort den sista `Dev`. |
| `403` | Du är inte personal, eller sessionen arbetar inuti ett annat konto. |
| `404` | Ingen sådan användare. |

---

## Team API-fel

Team-slutpunkter returnerar standardfel-kuvertet, alltid med `error_code` tillsammans med HTTP-statusen:

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

| Status | När det händer på en team-slutpunkt |
|---|---|
| `400` | Ett obligatoriskt fält saknas eller är ogiltigt, eller så är åtgärden inte tillåten i detta tillstånd (återaktivera en borttagen medlem, stänga av ägaren, ta bort en avdelning som någon är begränsad till). |
| `401` | Du skickade en API-nyckel till en slutpunkt som kräver en inloggad person — se [Autentisering](#authentication-these-endpoints-need-a-signed-in-person). |
| `403` | Du har inte `team_management`-behörighet, ändringen överskrider din egen åtkomst, eller åtgärden nekas när du arbetar inuti ett annat konto. |
| `404` | Ingen sådan medlem, inbjudan, avdelning eller användare. |
| `409` | Redan teammedlem, en väntande inbjudan finns redan, eller en avdelning med det namnet finns. |
| `429` | Teamplatserna är fulla, gränsen på 20 inbjudningar per dag är nådd, eller så har du nått API-hastighetsgränsen. |
| `504` | Inbjudan du försökte acceptera har gått ut. |

De delade koderna som varje slutpunkt kan returnera — `429` (hastighetsgräns) och `500` — listas med vägledning för återförsök i [Fel & Sidnumrering](errors-and-pagination.md).

---

## Relaterat

- [Teamhantering](../settings/team-management.md) — samma funktioner i instrumentpanelen, med skärmdumpar.
- [Autentisering](authentication.md) — hur man skickar en Firebase ID-token istället för en API-nyckel.
- [Kontakter API](contacts.md) — de kontakter som en medlems synlighetsbegränsningar gäller för.

