
# API för kanalanslutning

Den här guiden visar hur du ansluter meddelandekanaler till ett konto med hjälp av API:et. Den är skriven för utvecklare som bygger en integration eller wrapper, så den fokuserar på de exakta anropen, i vilken ordning de ska göras och vilka svar du får tillbaka.

Det finns ett mönster du behöver förstå från början, eftersom det gäller nästan alla kanaler här.

## Mönstret anslut-och-poll

De flesta kanaler kan inte anslutas med ett enda API-anrop. Att ansluta WhatsApp, Instagram eller Messenger innebär att kontoinnehavaren måste logga in på sitt eget leverantörskonto och godkänna åtkomst. Det finns **ingen headless-väg (helt automatiserad)** för det godkännandet – en verklig person måste öppna en URL i en webbläsare eller skanna en QR-kod med sin telefon.

Så flödet är alltid:

1. **Starta anslutningen** med ett `POST`. Svaret ger dig antingen en URL att öppna eller en QR-kod att visa.
2. **Överlämna detta till slutanvändaren** – öppna URL:en i deras webbläsare eller rendera QR-koden på skärmen så att de kan skanna den.
3. **Poll status-slutpunkten** med `GET` med korta intervall (varje sekund) tills statusen når ett anslutet tillstånd.

Din integrations uppgift är att driva den loopen: visa URL:en eller QR-koden och polla sedan tills det är klart. Planera ditt gränssnitt kring pollningen – en laddningssnurra med ett meddelande i stil med "väntar på att du ska slutföra i din webbläsare" fungerar bra.

::: note
**Obs:** Innan du börjar, se till att API-åtkomst är aktiverat för din plan och att du har en API-nyckel. Se [API-åtkomst](../integrations/api-access.md) för hur du genererar en. Alla förfrågningar nedan använder bas-URL:en `https://api.youraiconnector.com/v1` och du måste autentisera varje förfrågan. Se [Autentisering](authentication.md) för de fyra accepterade formerna – exemplen här använder `X-API-Key`-huvudet, med ett cURL-exempel per sida som visar den enklare `?apiKey=`-frågeformen.
:::


---

## Instagram + Messenger (Meta)

Instagram och Messenger ansluts tillsammans i ett flöde, eftersom båda körs via en Facebook-sida. Kontoinnehavaren auktoriserar via Facebook, du hämtar listan över sidor de hanterar och du väljer vilken sida som ska anslutas.

### Steg 1 - Starta Instagram + Messenger-anslutningen

```
POST /channels/meta/connect
```

Detta returnerar en URL för samtycke. Inga inloggningsuppgifter skickas i detta anrop – anslutningen auktoriseras helt i webbläsaren.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/channels/meta/connect?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/channels/meta/connect", {
  method: "POST",
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
// Open data.oauth_url in the end user's browser.
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/channels/meta/connect",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
# Open data["oauth_url"] in the end user's browser.
```

**Svar**

```json
{
  "success": true,
  "oauth_url": "https://www.facebook.com/v21.0/dialog/oauth?client_id=...&state=...",
  "state_token": "opaque-one-time-token",
  "connect_url": "https://api.youraiconnector.com/v1/channels/meta/connect/page?token=eyJhbGciOi...",
  "connect_url_expires_at": 1717000000000,
  "expires_at": "2026-06-10T12:30:00.000Z"
}
```

Öppna `oauth_url` i slutanvändarens webbläsare så att de kan logga in på Facebook och godkänna åtkomst. Anslutningsförsöket löper ut vid `expires_at` (cirka 30 minuter) – om det går ut, börja om. Behandla `state_token` som en kortlivad hemlighet och logga den inte.

### Enklaste alternativet för Instagram + Messenger: överlämna `connect_url`

Svaret innehåller även en färdig `connect_url`: en värdbaserad sida som kör hela flödet för kontoinnehavaren. De öppnar den, loggar in på Facebook, och när de har mer än en sida visas listan så att de kan välja vilken som ska anslutas – sedan rapporterar den framgång på egen hand. Ge denna länk till kontoinnehavaren istället för att själv öppna `oauth_url`, bygga en väljare för sidor och polla. Länken fungerar i cirka 30 minuter (`connect_url_expires_at`); om den löper ut, starta en ny anslutning. De manuella stegen nedan är till för integrationer som vill styra flödet och rendera sidväljaren själva.

### Steg 2 - Avläs statusen tills sidorna har laddats

```
GET /channels/meta/status
```

När användaren har slutfört inloggningen via Facebook, avläs denna slutpunkt med några sekunders mellanrum. Fältet `status` går igenom dessa steg:

| `status` | Betydelse |
|---|---|
| `pending` | Samtycke har ännu inte slutförts. Fortsätt vänta. |
| `token_received` | Auktoriserad, men listan över sidor laddas fortfarande. |
| `pages_loaded` | Sidor är tillgängliga - gå vidare till steg 3. |
| `connected` | En sida har valts och kanalen är aktiv. |

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/channels/meta/status" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/channels/meta/status", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
// Poll until data.status === "pages_loaded".
```

**Python**

```python
res = requests.get(
    "https://api.youraiconnector.com/v1/channels/meta/status",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
# Poll until data["status"] == "pages_loaded".
```

**Svar (när sidorna har laddats)**

```json
{
  "success": true,
  "status": "pages_loaded",
  "pages": [
    {
      "id": "1234567890",
      "name": "My Business Page",
      "category": "Local business",
      "instagram_business_account": {
        "id": "17890000000000000",
        "username": "mybusiness"
      }
    }
  ],
  "selected_page": null
}
```

### Steg 3 - Lista sidorna (valfritt)

Om du hellre vill hämta sidlistan separat (till exempel för att rendera en väljare), använd:

```
GET /channels/meta/pages
```

```bash
curl "https://api.youraiconnector.com/v1/channels/meta/pages" \
  -H "X-API-Key: YOUR_API_KEY"
```

Den returnerar samma `pages`-array som status-slutpunkten. (Slutpunkten `status` inkluderar redan sidorna, så detta anrop är bara för bekvämlighets skull.)

### Steg 4 - Välj sidan som ska anslutas

```
POST /channels/meta/select-page
```

Skicka `page_id` för den sida som användaren valde. Instagram-kontot som är kopplat till den sidan ansluts automatiskt; du behöver bara objektet `instagram` om du vill åsidosätta vilket Instagram-konto som ska användas.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/channels/meta/select-page" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "page_id": "1234567890" }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/channels/meta/select-page", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ page_id: "1234567890" }),
});
const data = await res.json();
```

**Python**

```python
res = requests.post(
    "https://api.youraiconnector.com/v1/channels/meta/select-page",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"page_id": "1234567890"},
)
data = res.json()
```

**Svar**

```json
{
  "success": true,
  "page_id": "1234567890",
  "instagram_business_account_id": "17890000000000000"
}
```

Kanalen är nu ansluten. En uppföljande `GET /channels/meta/status` kommer att rapportera `status: "connected"`.

### Lista inlägg för den anslutna sidan

```
GET /channels/meta/posts?platform=instagram
```

Returnerar de senaste inläggen från den sida du anslutit – Instagram-media eller Facebook-inlägg. Det är detta du renderar en väljare från när du konfigurerar en startpunkt (Entry Point) som reagerar på kommentarer på ett specifikt inlägg.

| Frågeparameter | Krävs | Beskrivning |
|---|---|---|
| `platform` | Ja | `instagram` eller `facebook`. Allt annat returnerar ett `400`. |
| `limit` | Nej | Hur många inlägg som ska returneras, `1`-`50`. Standard är `25`. |
| `after` | Nej | Markör för nästa sida – skicka med `nextCursor`-värdet från föregående svar. |

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/channels/meta/posts?platform=instagram&limit=25" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Svar**

```json
{
  "success": true,
  "connected": true,
  "platform": "instagram",
  "posts": [
    {
      "id": "17900000000000000",
      "caption": "New spring menu is live",
      "thumbnailUrl": "https://scontent.cdninstagram.com/...",
      "permalink": "https://www.instagram.com/p/Cxxxxxxxxxx/",
      "createdAt": "2026-05-02T09:12:00.000Z",
      "mediaType": "REELS"
    }
  ],
  "nextCursor": "QVFIUkxxxxxxxx"
}
```

`mediaType` är Instagrams egen etikett (`REELS`, `FEED`, `STORY`, eller formatet – `IMAGE`, `VIDEO`, `CAROUSEL_ALBUM`); för Facebook är det alltid `POST`. `nextCursor` är `null` på den sista sidan.

Om inget kan listas returnerar anropet fortfarande `200` med `connected: false` och en tom `posts`-array, plus ett `reason` som förklarar varför:

| `reason` | Vad du bör göra |
|---|---|
| _(saknas)_ | Ingen sida är ansluten än – kör anslutningsflödet först. |
| `no_instagram_account` | En Facebook-sida är ansluten men inget Instagram-företagskonto är länkat till den. Facebook-inlägg listas fortfarande korrekt. |
| `token_expired` | Den lagrade sidautentiseringen fungerar inte längre – anslut kanalen på nytt. |

### Koppla från Instagram + Messenger

```
DELETE /channels/meta
```

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/channels/meta" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Svar**

```json
{ "success": true, "disconnected": true }
```

Detta stoppar inkommande dirigering för både Instagram och Messenger. Det är idempotent - att anropa det när ingenting är anslutet lyckas fortfarande.

---

## WhatsApp Business

Detta ansluter ett officiellt WhatsApp Business-nummer. Numret måste redan finnas på kontot innan du anropar connect. Precis som med Meta godkänner kontoinnehavaren detta i sin webbläsare, sedan pollar du tills numret rapporterar `ONLINE`.

### Steg 1 - Starta WhatsApp Business-anslutningen

```
POST /channels/whatsapp/connect
```

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/channels/whatsapp/connect?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "phone_number": "+14155551234" }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/channels/whatsapp/connect", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ phone_number: "+14155551234" }),
});
const data = await res.json();
// Open data.oauth_url in the account holder's browser.
```

**Python**

```python
res = requests.post(
    "https://api.youraiconnector.com/v1/channels/whatsapp/connect",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"phone_number": "+14155551234"},
)
data = res.json()
# Open data["oauth_url"] in the account holder's browser.
```

| Fält | Krävs | Beskrivning |
|---|---|---|
| `phone_number` | Ja | Numret som ska anslutas, i E.164-format (t.ex. `+14155551234`). |
| `only_waba_sharing` | Nej | Begränsa auktoriseringen till att dela ett befintligt WhatsApp Business-konto, vilket hoppar över inställning av ny avsändare. Standard är `false`. |
| `retry` | Nej | Kör om auktoriseringen för ett nummer vars tidigare försök inte slutfördes. Standard är `false`. |
| `business_name` | Nej | Kosmetisk överskrivning för företagsnamnet som endast visas på samtyckesskärmen (max 256 tecken). Lagras ej. |
| `description` | Nej | Kosmetisk överskrivning för företagsbeskrivningen som endast visas på samtyckesskärmen (max 256 tecken). Lagras ej. |

**Svar**

```json
{
  "success": true,
  "status": "pending",
  "oauth_url": "https://www.facebook.com/v21.0/dialog/oauth?client_id=...&state=...",
  "state_token": "opaque-one-time-token",
  "expires_at": "2026-06-10T12:30:00.000Z"
}
```

Öppna `oauth_url` i kontoinnehavarens webbläsare för att auktorisera. När de har godkänt slutförs registreringen i bakgrunden.

### Steg 2 - Polla statusen tills ONLINE

```
GET /channels/whatsapp/connect/{phoneNumber}/status
```

Polla detta tills `status` är `ONLINE`.

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/channels/whatsapp/connect/+14155551234/status" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const phone = encodeURIComponent("+14155551234");
const res = await fetch(
  `https://api.youraiconnector.com/v1/channels/whatsapp/connect/${phone}/status`,
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
// Poll until data.status === "ONLINE".
```

**Python**

```python
import urllib.parse

phone = urllib.parse.quote("+14155551234")
res = requests.get(
    f"https://api.youraiconnector.com/v1/channels/whatsapp/connect/{phone}/status",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
# Poll until data["status"] == "ONLINE".
```

**Svar**

```json
{
  "success": true,
  "phone_number": "+14155551234",
  "channel": "whatsapp",
  "status": "ONLINE",
  "status_reason": null,
  "live": true
}
```

Fältet `status` kan vara:

| `status` | Betydelse |
|---|---|
| `PENDING` | Auktoriserat, godkännande pågår fortfarande. Fortsätt polla. |
| `ONLINE` | Anslutet och redo att skicka. |
| `RATE_LIMITED` | För många försök - vänta innan du försöker igen. |
| `REGISTRATION_FAILED` | Inställningen kunde inte slutföras. |
| `DELETED` | Registreringen finns inte längre. |

`live: true` betyder att statusen kontrollerades mot leverantören i realtid; `false` betyder att den kom från det senast cachade tillståndet.

### Koppla från ett WhatsApp Business-nummer

```
DELETE /channels/whatsapp/{phoneNumber}
```

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/channels/whatsapp/+14155551234" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Svar**

```json
{ "success": true, "phone_number": "+14155551234", "disconnected": true }
```

Själva numret stannar kvar på kontot, så att du kan återansluta det senare.

---

## WhatsApp Web

WhatsApp Web kopplar ett vanligt WhatsApp-nummer genom att skanna en QR-kod, precis som när du kopplar en enhet i WhatsApp-appen. Flödet är: starta sessionen, hämta QR-koden och visa den, och polla sedan tills statusen är `connected`.

### Steg 1 - Starta en WhatsApp Web-parningssession

```
POST /channels/whatsapp-web/connections
```

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/channels/whatsapp-web/connections?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "phone_number": "+15551230000" }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/channels/whatsapp-web/connections", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ phone_number: "+15551230000" }),
});
const data = await res.json();
```

**Python**

```python
res = requests.post(
    "https://api.youraiconnector.com/v1/channels/whatsapp-web/connections",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"phone_number": "+15551230000"},
)
data = res.json()
```

| Fält | Krävs | Beskrivning |
|---|---|---|
| `phone_number` | Ja | WhatsApp-numret som ska anslutas, i E.164-format. |
| `proxy_country` | Nej | ISO 3166-1 alpha-2 landskod för routningsregionen. Identifieras automatiskt från numret om den utelämnas. |
| `force_new` | Nej | Kassera alla befintliga sessioner och starta en ny parkoppling. Standardvärde är `false`. |
| `import_contacts` | Nej | Importera enhetens befintliga kontakter vid första anslutningen. Standardvärde är `false`. |
| `pause_ai_for_imported_contacts` | Nej | Vid import av kontakter, håll automatiska svar pausade för dem. Standardvärde är `true`. |
| `import_existing_chats` | Nej | Importera befintlig chatthistorik (kräver `import_contacts: true`). Standardvärde är `false`. |

**Svar**

```json
{
  "success": true,
  "phone_number": "+15551230000",
  "session_id": "session-id",
  "status": "qr_pending",
  "connect_url": "https://api.youraiconnector.com/v1/channels/whatsapp-web/connect?token=eyJhbGciOi...",
  "connect_url_expires_at": 1717000000000,
  "poll_qr_path": "/v1/channels/whatsapp-web/connections/%2B15551230000/qr",
  "poll_status_path": "/v1/channels/whatsapp-web/connections/%2B15551230000/status"
}
```

### Enklaste alternativet för WhatsApp Web: överlämna `connect_url`

Svaret innehåller en färdig `connect_url`: en hostad sida som visar QR-koden, uppdaterar den automatiskt när den roterar och växlar till ett lyckat meddelande så fort numret har kopplats. Ge bara denna länk till kontoinnehavaren (öppna den i en webbläsare, skicka den till dem eller visa den som en QR-kod/knapp) och låt dem skanna den med WhatsApp – du behöver inte hämta QR-koden eller polla något själv. Länken fungerar i cirka 30 minuter (`connect_url_expires_at`); om den löper ut innan de är klara, starta en ny anslutning för att få en ny.

Detta är den rekommenderade metoden när en person kan öppna en länk. De manuella stegen nedan (hämta QR-koden själv, polla statusen) är till för integrationer som vill rendera QR-koden i sitt eget gränssnitt istället.

Svaret ger dig även den exakta `poll_qr_path` och `poll_status_path` att använda, så att du inte behöver bygga dem själv.

### Steg 2 - Hämta QR-koden och visa den

```
GET /channels/whatsapp-web/connections/{phoneNumber}/qr
```

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/channels/whatsapp-web/connections/+15551230000/qr" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const phone = encodeURIComponent("+15551230000");
const res = await fetch(
  `https://api.youraiconnector.com/v1/channels/whatsapp-web/connections/${phone}/qr`,
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
// Render data.qr_data_url as an <img src> for the user to scan.
```

**Python**

```python
import urllib.parse

phone = urllib.parse.quote("+15551230000")
res = requests.get(
    f"https://api.youraiconnector.com/v1/channels/whatsapp-web/connections/{phone}/qr",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
# Render data["qr_data_url"] for the user to scan.
```

**Svar**

```json
{
  "success": true,
  "phone_number": "+15551230000",
  "status": "qr_pending",
  "qr_code": "2@raw-qr-payload-string...",
  "qr_data_url": "data:image/png;base64,iVBORw0KGgo...",
  "expires_at": "2026-06-10T12:05:00.000Z"
}
```

Visa QR-koden så att användaren kan skanna den med sin telefon (WhatsApp > Länkade enheter > Länka en enhet):

- `qr_data_url` är en bild som är redo att användas - placera den direkt i en `<img src>`.
- `qr_code` är rådatan om du hellre vill generera bilden själv.

QR-koden är kortlivad. Om du anropar detta direkt efter att sessionen startats kan du få ett `404` med "QR code not available yet" - vänta bara en stund och försök igen. Om du får ett `410` ("QR code expired"), starta om anslutningen för att få en ny kod.

### Steg 3 - Polla statusen tills anslutning upprättats

```
GET /channels/whatsapp-web/connections/{phoneNumber}/status
```

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/channels/whatsapp-web/connections/+15551230000/status" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const phone = encodeURIComponent("+15551230000");
const res = await fetch(
  `https://api.youraiconnector.com/v1/channels/whatsapp-web/connections/${phone}/status`,
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
// Poll until data.status === "connected" (or "open").
```

**Python**

```python
import urllib.parse

phone = urllib.parse.quote("+15551230000")
res = requests.get(
    f"https://api.youraiconnector.com/v1/channels/whatsapp-web/connections/{phone}/status",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
# Poll until data["status"] == "connected" (or "open").
```

**Svar**

```json
{
  "success": true,
  "phone_number": "+15551230000",
  "status": "connected",
  "has_qr": false,
  "qr_expires_at": null,
  "last_activity": null,
  "message_count": null,
  "proxy": null,
  "live": true
}
```

| `status` | Betydelse |
|---|---|
| `not_initialized` | Ingen session ännu (terminalt fel). |
| `qr_pending` | Väntar på att QR-koden ska skannas. |
| `connecting` | Skannad, slutför konfigurationen. |
| `connected` / `open` | Länkad och aktiv - detta är en lyckad anslutning. |
| `disconnected` | Sessionen avslutad (terminalt fel). |

### Koppla från en WhatsApp Web-session

```
DELETE /channels/whatsapp-web/connections/{phoneNumber}
```

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/channels/whatsapp-web/connections/+15551230000" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Svar**

```json
{ "success": true, "phone_number": "+15551230000", "status": "removed" }
```

Detta kopplar bort enheten och tar bort anslutningen. Det rensar alltid lokalt tillstånd, så det är idempotent även om den underliggande sessionen redan var borta.

---

## Telegram

> **Tillgänglighet:** Telegram ansluter som vilken annan kanal som helst och är öppen för alla konton — du behöver inte aktivera den separat. Telegram-slutpunkterna nedan kan fortfarande returnera `403` om Telegram inte ingår i kontots abonnemang, i vilket fall felet lyder `"This channel is not included in your current plan. Upgrade to unlock it."`.

Telegram ansluter ett personligt konto via telefonnummer plus en engångskod (och ett lösenord för tvåfaktorsautentisering, om kontot har ett sådant inställt). Flödet är: starta sessionen, skicka in koden, skicka eventuellt in lösenordet, och bekräfta sedan via status.

### Steg 1 - Starta en Telegram-anslutningssession

```
POST /channels/telegram/connect
```

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/channels/telegram/connect?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "phone_number": "+14155550100" }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/channels/telegram/connect", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ phone_number: "+14155550100" }),
});
const data = await res.json();
```

**Python**

```python
res = requests.post(
    "https://api.youraiconnector.com/v1/channels/telegram/connect",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"phone_number": "+14155550100"},
)
data = res.json()
```

| Fält | Krävs | Beskrivning |
|---|---|---|
| `phone_number` | Ja | Kontots telefonnummer för anslutning, i E.164-format. |
| `mode` | Nej | `code` (standard) skickar en engångskod till kontot; `qr` returnerar en inloggningstoken och QR-URL att visa. |
| `proxy_country` | Nej | ISO 3166-1 alpha-2 landskod för den utgående nätverksrutten. |
| `force_new` | Nej | När `true`, tas alla befintliga sessioner bort och en ny startas. |

**Svar**

```json
{
  "success": true,
  "phone_number": "+14155550100",
  "status": "code_required",
  "session_id": "session-id",
  "connect_url": "https://api.youraiconnector.com/v1/channels/telegram/connect/page?token=eyJhbGciOi...",
  "connect_url_expires_at": 1717000000000
}
```

I `code`-läge tar kontot emot en inloggningskod i Telegram och `status` är `code_required`. (I `qr`-läge inkluderar svaret även `login_token` och `qr_url` att visa för skanning, och `status` är `qr_required`.)

### Enklaste alternativet för Telegram: överlämna `connect_url`

Svaret innehåller en färdig `connect_url`: en värdbaserad sida som slutför anslutningen på egen hand. I `code`-läge anger kontoinnehavaren inloggningskoden - och ett lösenord för tvåstegsverifiering om kontot har ett sådant. I `qr`-läge visar sidan en QR-kod som uppdaterar sig själv för att skannas från Telegram-appen. Oavsett metod rapporterar den framgång automatiskt, så du kan helt enkelt ge den här länken till kontoinnehavaren istället för att bygga ett eget gränssnitt och polla. Länken fungerar i cirka 30 minuter (`connect_url_expires_at`); om den löper ut, starta en ny anslutning för att få en ny.

De manuella stegen nedan (samla in koden själv, skicka in den, polla statusen; eller rendera `qr_url` och polla) är till för integrationer som vill rendera gränssnittet själva.

### Steg 2 - Skicka in inloggningskoden

```
POST /channels/telegram/connect/{phoneNumber}/verify-code
```

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/channels/telegram/connect/+14155550100/verify-code" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "code": "12345" }'
```

**JavaScript**

```javascript
const phone = encodeURIComponent("+14155550100");
const res = await fetch(
  `https://api.youraiconnector.com/v1/channels/telegram/connect/${phone}/verify-code`,
  {
    method: "POST",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ code: "12345" }),
  }
);
const data = await res.json();
```

**Python**

```python
import urllib.parse

phone = urllib.parse.quote("+14155550100")
res = requests.post(
    f"https://api.youraiconnector.com/v1/channels/telegram/connect/{phone}/verify-code",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"code": "12345"},
)
data = res.json()
```

**Svar**

```json
{
  "success": true,
  "phone_number": "+14155550100",
  "status": "connected",
  "telegram_user_id": "100000001",
  "username": "myhandle"
}
```

Om `status` är `connected` är du klar. Om kontot har tvåfaktorsautentisering aktiverat kommer `status` att vara `password_required` istället - gå till steg 3.

### Steg 3 - Skicka in lösenordet för tvåfaktorsautentisering (endast vid behov)

```
POST /channels/telegram/connect/{phoneNumber}/verify-password
```

Anropa endast detta när steg 2 returnerade `password_required`.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/channels/telegram/connect/+14155550100/verify-password" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "password": "the-2fa-password" }'
```

**JavaScript**

```javascript
const phone = encodeURIComponent("+14155550100");
const res = await fetch(
  `https://api.youraiconnector.com/v1/channels/telegram/connect/${phone}/verify-password`,
  {
    method: "POST",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ password: "the-2fa-password" }),
  }
);
const data = await res.json();
```

**Python**

```python
import urllib.parse

phone = urllib.parse.quote("+14155550100")
res = requests.post(
    f"https://api.youraiconnector.com/v1/channels/telegram/connect/{phone}/verify-password",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"password": "the-2fa-password"},
)
data = res.json()
```

**Svar**

```json
{
  "success": true,
  "phone_number": "+14155550100",
  "status": "connected",
  "telegram_user_id": "100000001",
  "username": "myhandle"
}
```

### Kontrollera Telegram-status

```
GET /channels/telegram/connect/{phoneNumber}/status
```

```bash
curl "https://api.youraiconnector.com/v1/channels/telegram/connect/+14155550100/status" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Svar**

```json
{
  "success": true,
  "phone_number": "+14155550100",
  "status": "connected",
  "telegram_user_id": "100000001",
  "live": true
}
```

`status` kan vara `connected`, `code_required`, `password_required`, `initializing`, `disconnected`, `not_initialized` eller `error`.

### Koppla från Telegram

```
DELETE /channels/telegram/{phoneNumber}
```

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/channels/telegram/+14155550100" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Svar**

```json
{ "success": true, "phone_number": "+14155550100", "status": "removed" }
```

Idempotent - upprepade anrop lyckas.

---

## Instagram (personligt konto)

> Betaversion med begränsad tillgänglighet, aktiveras per konto. Detta ansluter ett personligt Instagram-konto genom att logga in med dess användarnamn och lösenord (inte det officiella Business API:et). Om kontot inte är aktiverat för betan returnerar anslutningsanropet ett behörighetsfel.

Eftersom detta kräver kontoinnehavarens egna Instagram-inloggning är den enklaste vägen att ge dem den värdbaserade `connect_url` och låta dem ange sina inloggningsuppgifter där – din integration hanterar aldrig lösenordet.

### Steg 1 - Starta en Instagram-anslutning (personlig)

```
POST /channels/instagram-private/connect
```

Skicka Instagram `username` och `password`.

**Svar**

```json
{
  "success": true,
  "status": "connected",
  "connect_url": "https://api.youraiconnector.com/v1/channels/instagram-private/connect/page?token=eyJhbGciOi...",
  "connect_url_expires_at": 1717000000000
}
```

Om kontot har tvåfaktorsautentisering eller om Instagram presenterar en kontrollpunkt, returneras `status` som `two_factor_required` eller `challenge_required` – skicka koden till `/connect/{id}/verify-2fa` eller `/connect/{id}/verify-challenge` nedan, och polla sedan `/connect/{id}/status` tills `connected`. `{id}` är det normaliserade Instagram-användarnamnet som returneras som `account_id`/`username` i svaret ovan – använd det i varje steg nedan.

### Steg 2 – Skicka in tvåfaktorskoden (om efterfrågat)

```
POST /channels/instagram-private/connect/{id}/verify-2fa
```

Anropa endast detta när steg 1 (eller steg 3) returnerade `two_factor_required`.

```bash
curl -X POST "https://api.youraiconnector.com/v1/channels/instagram-private/connect/yourbrand/verify-2fa" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "code": "123456" }'
```

**Svar**

```json
{
  "success": true,
  "account_id": "yourbrand",
  "status": "connected",
  "ig_user_id": "17890000000000000",
  "username": "yourbrand"
}
```

`status` kan returnera `connected` (klart), `two_factor_required` (fel kod, försök igen), eller `challenge_required` (Instagram kräver även en kontrollpunktskod – gå till steg 3).

### Steg 3 – Skicka in kontrollpunktskoden (om efterfrågat)

```
POST /channels/instagram-private/connect/{id}/verify-challenge
```

Anropa endast detta när ett tidigare steg returnerade `challenge_required`. Samma format för förfrågan och svar som i steg 2 ovan.

```bash
curl -X POST "https://api.youraiconnector.com/v1/channels/instagram-private/connect/yourbrand/verify-challenge" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "code": "123456" }'
```

### Kontrollera status för Instagram (personligt)

```
GET /channels/instagram-private/connect/{id}/status
```

Polla detta tills `status` är `connected`, eller tills det rapporterar ett terminalt fel.

```bash
curl "https://api.youraiconnector.com/v1/channels/instagram-private/connect/yourbrand/status" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Svar**

```json
{
  "success": true,
  "account_id": "yourbrand",
  "status": "connected",
  "ig_user_id": "17890000000000000",
  "username": "yourbrand",
  "live": true
}
```

`status` kan vara `connected`, `two_factor_required`, `challenge_required`, `initializing`, `disconnected`, `not_initialized`, eller `error`. `live: true` innebär att detta lästes live från anslutningsarbetaren istället för ett cachat värde.

### Enklaste alternativet för Instagram (personlig): överlämna `connect_url`

Svaret innehåller en `connect_url`: en värdbaserad sida där kontoinnehavaren anger sitt Instagram-användarnamn och lösenord (samt en 2FA- eller kontrollpunktskod om Instagram efterfrågar en), och som rapporterar framgång på egen hand. Inloggningsuppgifterna går direkt till Instagram och lagras inte. Ge denna länk till kontoinnehavaren istället för att samla in deras lösenord i ditt eget gränssnitt. Länken fungerar i cirka 30 minuter (`connect_url_expires_at`).

### Koppla från Instagram (personligt)

```
DELETE /channels/instagram-private/{id}
```

Idempotent - upprepade anrop lyckas.

### Synkronisera följare

```
POST /channels/instagram-private/{id}/sync-followers
```

Utlöser manuellt en synkronisering av följare för ett anslutet konto – samma jobb som körs automatiskt i bakgrunden, här exponerat som en "Uppdatera följare"-åtgärd vid behov. Den hämtar kontots aktuella lista över följare, registrerar nya personer och (när en Live-kampanj har följarutskick aktiverat) skickar ett första direktmeddelande till nya följare, upp till en daglig gräns.

```bash
curl -X POST "https://api.youraiconnector.com/v1/channels/instagram-private/yourbrand/sync-followers" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Svar**

```json
{
  "success": true,
  "accountId": "yourbrand",
  "totalFollowers": 1204,
  "newFollowers": 6,
  "dmsSent": 6,
  "isBaselineSeed": false
}
```

> Dessa fem fält är den enda platsen på den här sidan som returnerar `camelCase` istället för `snake_case` – det är så den här slutpunkten är konfigurerad idag, inte ett skrivfel. `isBaselineSeed: true` betyder att detta var den allra första synkroniseringen efter anslutning, vilket endast registrerar den inledande listan över följare och aldrig skickar utskick via direktmeddelanden (så `dmsSent` är alltid `0` vid den körningen).

Det allra första anropet för ett konto kan ta en stund (eftersom hela listan över följare gås igenom); senare anrop går snabbare eftersom endast nya följare behöver jämföras. `404` betyder att kontot inte är anslutet; `412` betyder att anslutningen inte har slutat initieras ännu – vänta och försök igen.

---

## LINE

LINE är den enklaste kanalen att ansluta eftersom det inte krävs någon omdirigering i webbläsaren eller avsökning (polling). Kunden skapar en Messaging API-kanal i LINE Developers-konsolen, kopierar två värden och du skickar in dem i ett enda anrop. Du ger dem sedan tillbaka en webhook-URL som de klistrar in i konsolen.

### Steg 1 - Anslut med kanalens inloggningsuppgifter

```
POST /channels/line
```

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/channels/line?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "channel_access_token": "LONG_LIVED_CHANNEL_ACCESS_TOKEN",
    "channel_secret": "CHANNEL_SECRET"
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/channels/line", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    channel_access_token: "LONG_LIVED_CHANNEL_ACCESS_TOKEN",
    channel_secret: "CHANNEL_SECRET",
  }),
});
const data = await res.json();
```

**Python**

```python
res = requests.post(
    "https://api.youraiconnector.com/v1/channels/line",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "channel_access_token": "LONG_LIVED_CHANNEL_ACCESS_TOKEN",
        "channel_secret": "CHANNEL_SECRET",
    },
)
data = res.json()
```

| Fält | Krävs | Beskrivning |
|---|---|---|
| `channel_access_token` | Ja | Det officiella kontots långlivade åtkomsttoken för Messaging API-kanalen. Används för att skicka och ta emot meddelanden. |
| `channel_secret` | Ja | Messaging API-kanalens hemlighet, används för att verifiera inkommande händelsesignaturer. |
| `channel_id` | Nej | Det numeriska kanal-ID:t. Endast för information. |

**Svar**

```json
{
  "success": true,
  "status": "connected",
  "bot_user_id": "Uxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "basic_id": "@mybusiness",
  "display_name": "My Business",
  "picture_url": "https://...",
  "chat_mode": "bot",
  "chat_mode_ok": true,
  "webhook_url": "https://api.youraiconnector.com/line/webhook/..."
}
```

Två fält är viktiga för vad du gör härnäst:

- **`webhook_url`** - kunden måste klistra in detta i fältet **Webhook URL** för sin LINE-kanal i LINE Developers-konsolen (och aktivera "Use webhook"). Innan de gör det kommer inga inkommande meddelanden fram. Visa detta tydligt för dem.
- **`chat_mode_ok`** - när `false` är det officiella kontot i "chatt"-läge och kommer inte att ta emot eller skicka meddelanden förrän det växlas till "bot"-läge i LINE Official Account Manager. Styr din onboarding baserat på denna flagga och be kunden att växla läge.

> `channel_access_token` och `channel_secret` returneras aldrig av någon slutpunkt. Lagra dem på din sida om du behöver dem igen; annars klistra in dem på nytt från LINE-konsolen.

Det `bot_user_id` som returneras här är den anslutningsidentifierare du använder i status-, verifierings- och frånkopplingsanropen nedan.

### Steg 2 - Verifiera på nytt efter webhook-konfiguration

```
POST /channels/line/{botUserId}/verify-webhook
```

När kunden har konfigurerat webhook-URL:en och växlat till bot-läge, anropa detta för att omvalidera den lagrade token och uppdatera det cachade chattläget.

```bash
curl -X POST "https://api.youraiconnector.com/v1/channels/line/Uxxxxxxxx.../verify-webhook" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Svar**

```json
{
  "success": true,
  "token_valid": true,
  "chat_mode": "bot",
  "chat_mode_ok": true,
  "webhook_url": "https://api.youraiconnector.com/line/webhook/..."
}
```

Om `token_valid` är `false`, autentiserar den lagrade åtkomsttoken inte längre – be kunden utfärda en ny i konsolen och anropa `POST /channels/line` igen med den nya token.

### Kontrollera LINE-status

```
GET /channels/line/{botUserId}/status
```

```bash
curl "https://api.youraiconnector.com/v1/channels/line/Uxxxxxxxx.../status" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Svar**

```json
{
  "success": true,
  "bot_user_id": "Uxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "channel": "line",
  "status": "connected",
  "basic_id": "@mybusiness",
  "display_name": "My Business",
  "picture_url": "https://...",
  "chat_mode": "bot",
  "is_active": true,
  "live": false
}
```

LINE har inget live-statusflöde, så `live` är alltid `false` här – värdena återspeglar tillståndet som fångades vid anslutningstillfället (eller vid senaste verifiering).

### Koppla från LINE

```
DELETE /channels/line/{botUserId}
```

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/channels/line/Uxxxxxxxx..." \
  -H "X-API-Key: YOUR_API_KEY"
```

**Svar**

```json
{ "success": true, "status": "removed", "bot_user_id": "Uxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }
```

---

## Viber

Viber ansluts på samma sätt som LINE – klistra in botens autentiseringstoken från Viber Admin Panel i ett anrop – med en skillnad som är värd att känna till: anslutningen REGISTRERAR även vår webhook på din bot direkt, så det finns inget separat konsolsteg efteråt. Det innebär också att ett anslutningsförsök kan misslyckas om vår ingress inte kan svara på Vibers synkrona webhook-kontroll, inte bara om själva token är felaktig.

### Steg 1 – Anslut med botens autentiseringstoken

```
POST /channels/viber
```

| Fält | Krävs | Beskrivning |
|---|---|---|
| `auth_token` | Ja | Botens autentiseringstoken, från Viber Admin Panel (My Bot Settings). |

```bash
curl -X POST "https://api.youraiconnector.com/v1/channels/viber?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "auth_token": "444d5555e6666f7777a8888b9999c000" }'
```

**Svar**

```json
{
  "success": true,
  "status": "connected",
  "bot_id": "botIdFromViber",
  "bot_name": "My Business Bot",
  "bot_avatar": "https://...",
  "bot_uri": "mybusinessbot",
  "subscribers_count": 0,
  "webhook_url": "https://api.youraiconnector.com/v1/incoming-viber-message/...",
  "event_types": ["delivered", "seen", "failed", "subscribed", "unsubscribed", "conversation_started"]
}
```

Autentiseringstoken skickas aldrig tillbaka av någon slutpunkt – lagra den på din sida om du behöver klistra in den igen. `bot_id` är anslutningsidentifieraren som används av status-, verifierings- och frånkopplingsanropen nedan.

### Kontrollera Viber-status

```
GET /channels/viber/{botId}/status
```

Rapporterar det lagrade anslutningstillståndet. Lägg till `?live=true` för att även kontrollera boten mot Viber igen och uppdatera den cachade webhook-registreringen – användbart innan du antar att en tyst bot faktiskt är trasig.

```bash
curl "https://api.youraiconnector.com/v1/channels/viber/botIdFromViber/status?live=true" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Svar**

```json
{
  "success": true,
  "bot_id": "botIdFromViber",
  "channel": "viber",
  "status": "connected",
  "bot_name": "My Business Bot",
  "bot_avatar": "https://...",
  "bot_uri": "mybusinessbot",
  "webhook_url": "https://api.youraiconnector.com/v1/incoming-viber-message/...",
  "registered_webhook": "https://api.youraiconnector.com/v1/incoming-viber-message/...",
  "webhook_ok": true,
  "subscribers_count": 128,
  "is_active": true,
  "live": true
}
```

`webhook_ok: false` betyder att botens webhook inte längre pekar på oss – inkommande meddelanden når inte fram. Detta innebär vanligtvis att ett annat verktyg anslöt samma bot efteråt (Vibers webhook-registrering fungerar enligt principen "sista skrivning vinner"). Åtgärda det med verifieringsanropet nedan, du behöver inte be kunden klistra in sin token igen. `live` är `false` när svaret är det senast cachade tillståndet snarare än en färsk kontroll mot Viber.

### Omregistrera webhooken

```
POST /channels/viber/{botId}/verify-webhook
```

Reparationsåtgärden för `webhook_ok: false` – omregistrerar vår webhook på boten med hjälp av den redan lagrade autentiseringstoken.

```bash
curl -X POST "https://api.youraiconnector.com/v1/channels/viber/botIdFromViber/verify-webhook" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Svar**

```json
{ "success": true, "token_valid": true, "webhook_ok": true, "webhook_url": "https://api.youraiconnector.com/v1/incoming-viber-message/...", "event_types": ["delivered", "seen", "failed", "subscribed", "unsubscribed", "conversation_started"] }
```

`token_valid: false` betyder att den lagrade token inte längre fungerar – anslut igen med `POST /channels/viber` och en ny token.

### Koppla från Viber

```
DELETE /channels/viber/{botId}
```

Avregistrerar vår webhook hos Viber (best-effort) och tar bort anslutningen.

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/channels/viber/botIdFromViber" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Svar**

```json
{ "success": true, "status": "removed", "bot_id": "botIdFromViber", "webhook_removed": true }
```

---

## TikTok

> **Tillgänglighet:** Beta med begränsad tillgänglighet, aktiveras per konto. Att ansluta TikTok returnerar ett behörighetsfel tills kontot har aktiverats för det.

TikTok Business Messaging är en fullständig OAuth-kanal likt Meta, men enklare när det gäller polling: det finns inget dedikerat status-pollingsteg att bygga mot, eftersom det anslutna kontot dyker upp av sig självt när TikTok omdirigerar tillbaka och anslutningen har skrivits. Status-slutpunkten nedan finns till för att bekräfta tillstånd vid behov (supportverktyg, hälsokontroller), inte som något du behöver loopa under anslutningen.

### Steg 1 - Starta TikTok-anslutningen

```
POST /channels/tiktok/connect
```

Kräver inga inloggningsuppgifter - kontoinnehavaren auktoriserar helt i sin webbläsare.

```bash
curl -X POST "https://api.youraiconnector.com/v1/channels/tiktok/connect?apiKey=YOUR_API_KEY"
```

**Svar**

```json
{
  "success": true,
  "status": "pending_authorization",
  "oauth_url": "https://www.tiktok.com/v2/auth/authorize?client_key=...&state=...",
  "state_token": "opaque-one-time-token",
  "expires_at": "2026-06-10T12:30:00.000Z"
}
```

Öppna `oauth_url` i kontoinnehavarens webbläsare så att de kan logga in på TikTok och godkänna åtkomst. Tillståndet löper ut vid `expires_at` (cirka 30 minuter) - om det löper ut, börja om. Det finns ingen `connect_url`-genväg för värdbaserad sida för TikTok; att öppna `oauth_url` själv är den enda vägen.

### Kontrollera TikTok-status

```
GET /channels/tiktok/{openId}/status
```

`openId` är TikTok Business-kontots open_id, vilket är känt när OAuth-återanropet har körts.

```bash
curl "https://api.youraiconnector.com/v1/channels/tiktok/openIdFromTikTok/status" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Svar**

```json
{
  "success": true,
  "open_id": "openIdFromTikTok",
  "channel": "tiktok",
  "status": "connected",
  "business_id": "openIdFromTikTok",
  "username": "mybusiness",
  "display_name": "My Business",
  "avatar_url": "https://...",
  "status_reason": null,
  "is_active": true,
  "live": false
}
```

TikTok har ingen billig live-hälsokontroll, så `live` är alltid `false` här - fälten återspeglar vad anslutningen (eller den senaste token-uppdateringen) skrev. `status: "reauth_required"` med `status_reason` inställt innebär att kontot måste gå igenom anslutningen igen; TikTok-tokens uppdateras automatiskt årligen, och detta är vad som visas om den uppdateringen misslyckas.

### Koppla från TikTok

```
DELETE /channels/tiktok/{openId}
```

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/channels/tiktok/openIdFromTikTok" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Svar**

```json
{ "success": true, "status": "removed", "open_id": "openIdFromTikTok" }
```

---

## GoHighLevel

GoHighLevel (GHL) är en CRM-integration, inte en meddelandekanal - att ansluta den förbrukar inte en kanalplats i planen, eftersom den använder kontots befintliga kanaler istället för att lägga till en ny. Det är också den enda integrationen på denna sida som kan ha **fler än en anslutning samtidigt**: varje GHL-underkonto ("plats") som kunden installerar appen på får sin egen post.

### Steg 1 - Starta GHL-anslutningen

```
POST /channels/ghl/connect
```

| Fält | Krävs | Beskrivning |
|---|---|---|
| `brand` | Nej | Vilken GHL-marknadsplatslista som ska auktoriseras. Standard är standardlistan - endast relevant om din distribution har fler än en marknadsplatsapp konfigurerad. |

```bash
curl -X POST "https://api.youraiconnector.com/v1/channels/ghl/connect?apiKey=YOUR_API_KEY"
```

**Svar**

```json
{
  "success": true,
  "status": "pending_authorization",
  "oauth_url": "https://marketplace.gohighlevel.com/oauth/chooselocation?client_id=...&state=...",
  "state_token": "opaque-one-time-token",
  "brand": "dmchamp",
  "expires_at": "2026-06-10T12:30:00.000Z"
}
```

Öppna `oauth_url` i kontoinnehavarens webbläsare så att de kan välja en GHL-plats och godkänna åtkomst. Tillståndet löper ut vid `expires_at` (cirka 30 minuter).

### Lista GHL-anslutningar

```
GET /channels/ghl/status
```

Till skillnad från andra kanaler är detta inte status för en enskild anslutning - den listar varje plats som kontot har anslutit.

```bash
curl "https://api.youraiconnector.com/v1/channels/ghl/status" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Svar**

```json
{
  "success": true,
  "connections": [
    {
      "location_id": "abc123location",
      "company_id": "xyz789company",
      "brand": "dmchamp",
      "status": "connected",
      "status_reason": null,
      "scopes": ["conversations.readonly", "conversations.write", "conversations/message.write"],
      "connected_at": "2026-06-01T10:00:00.000Z",
      "conversation_provider_id": "provider-id-in-ghl",
      "trigger_subscriptions": [
        { "id": "sub_1", "key": "InboundMessage", "workflow_id": "wf_123" }
      ]
    }
  ]
}
```

### Koppla från en GHL-plats

```
DELETE /channels/ghl/{locationId}
```

Tar bort anslutningen här, vilket stoppar all synkronisering och alla utlösare för den platsen. Detta avinstallerar inte appen på GHL-sidan - kunden tar bort den från sina GHL-marknadsplatsinstallationer om de vill det också.

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/channels/ghl/abc123location" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Svar**

```json
{ "success": true, "status": "disconnected", "location_id": "abc123location" }
```

---

## Telefonnummer (köp och frigör)

Istället för att ansluta ett befintligt nummer kan du köpa ett nytt WhatsApp-kompatibelt nummer direkt. Sök efter tillgängliga nummer, köp ett och avläs sedan statusen tills etableringen är klar.

::: note
**Obs:** Nummer som köps här har stöd för WhatsApp. Registrering av WhatsApp-avsändare körs i bakgrunden efter köpet, så du bör avläsa statusen tills den når `ONLINE` innan du skickar. Krediter dras vid köptillfället och återbetalas **inte** när du släpper numret.
:::


### Steg 1 - Sök efter tillgängliga nummer

```
GET /phone-numbers/available?country_code=ISO2
```

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/phone-numbers/available?country_code=US&apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/phone-numbers/available?country_code=US",
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
```

**Python**

```python
res = requests.get(
    "https://api.youraiconnector.com/v1/phone-numbers/available",
    params={"country_code": "US"},
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

| Frågeparameter | Krävs | Beskrivning |
|---|---|---|
| `country_code` | Ja | ISO 3166-1 alpha-2 landskod att söka i (t.ex. `US`, `GB`, `NL`). |
| `type` | Nej | Föredragen nummerklass, `local` eller `mobile`. Båda klasserna kan fortfarande returneras. |

**Svar**

```json
{
  "success": true,
  "phone_numbers": [
    {
      "phone_number": "+14155551234",
      "purchase_credits": 50,
      "monthly_credits": 50,
      "cost_usd": 1.15
    }
  ]
}
```

Varje resultat visar engångskostnaden `purchase_credits` och den återkommande kostnaden `monthly_credits`. Ett nummer som tillhandahålls av plattformen kostar minst 50 krediter per månad, vilket ökar med operatörens eget månadspris, och debiteras vid köp och vid varje förnyelse. Använd `purchase_credits` / `monthly_credits` som sökningen returnerar; härled aldrig ett pris själv. Den första sökningen på ett nytt konto etablerar vissa underliggande resurser, så den kan vara något långsammare än senare sökningar.

### Steg 2 - Köp ett nummer

```
POST /phone-numbers
```

Använd ett `phone_number` från sökresultaten.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/phone-numbers" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phone_number": "+14155551234",
    "country_code": "US",
    "display_name": "Support line"
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/phone-numbers", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    phone_number: "+14155551234",
    country_code: "US",
    display_name: "Support line",
  }),
});
const data = await res.json();
```

**Python**

```python
res = requests.post(
    "https://api.youraiconnector.com/v1/phone-numbers",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "phone_number": "+14155551234",
        "country_code": "US",
        "display_name": "Support line",
    },
)
data = res.json()
```

| Fält | Krävs | Beskrivning |
|---|---|---|
| `phone_number` | Ja | Ett nummer som returnerats av sökningen efter tillgängliga nummer, i E.164-format. |
| `country_code` | Ja | ISO 3166-1 alpha-2 landskod (t.ex. `US`). |
| `display_name` | Nej | En användarvänlig etikett. Standard är telefonnumret. |
| `category` | Nej | Valfri kategorietikett. |

**Svar**

```json
{
  "success": true,
  "phone_number": "+14155551234",
  "channel": "whatsapp",
  "whatsapp_status": "PURCHASED",
  "outgoing_status": "PURCHASED",
  "status": "PURCHASED",
  "purchase_credits": 50,
  "monthly_credits": 50
}
```

Numret startar i tillståndet `PURCHASED`. WhatsApp-registreringen fortsätter sedan i bakgrunden: `PURCHASED` -> `PENDING` -> `ONLINE`.

> Om köpet misslyckas eftersom en företagsadress saknas eller en annan obligatorisk uppgift inte har angetts, får du ett `400` med en beskrivande `error`. Ställ in den saknade uppgiften och försök igen.

### Steg 3 - Polla tills ONLINE

```
GET /phone-numbers/{phoneNumber}/status
```

Detta är den delade slutpunkten för telefonnummerstatus - den fungerar för köpta WhatsApp-nummer såväl som för dina andra anslutna nummer.

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/phone-numbers/+14155551234/status" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const phone = encodeURIComponent("+14155551234");
const res = await fetch(
  `https://api.youraiconnector.com/v1/phone-numbers/${phone}/status`,
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
// Poll until data.status === "ONLINE".
```

**Python**

```python
import urllib.parse

phone = urllib.parse.quote("+14155551234")
res = requests.get(
    f"https://api.youraiconnector.com/v1/phone-numbers/{phone}/status",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
# Poll until data["status"] == "ONLINE".
```

**Svar**

```json
{
  "success": true,
  "phone_number": "+14155551234",
  "channel": "whatsapp",
  "status": "ONLINE",
  "status_reason": null,
  "live": true
}
```

### Steg 4 - Frisläpp ett nummer

```
DELETE /phone-numbers/{phoneNumber}
```

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/phone-numbers/+14155551234" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Svar**

```json
{ "success": true, "phone_number": "+14155551234", "released": true }
```

Vad detta gör beror på vems nummer det är.

För ett nummer som **hyrts via plattformen** är det en verklig frigivning: WhatsApp-avsändaren avregistreras, numret lämnas tillbaka till operatören och tas bort från kontot, en 7-dagars nedkylningsperiod tillämpas under vilken numret inte kan återköpas av någon, och inga krediter återbetalas.

För ett nummer där **kontot tog med sig sitt eget** (eget Twilio-konto, egen Meta-app eller WhatsApp Business-konto, eller en Android SMS-gateway), tar samma anrop bara bort det från kontot. Ingenting frigörs hos den uppströmsleverantören och ingen nedkylningsperiod skrivs, så numret kan återanslutas omedelbart. Dess WhatsApp-avsändarregistrering, om en sådan fanns, kan överleva eller inte: nedmonteringen försöker radera avsändaren med hjälp av kontots plattformshanterade Twilio-uppgifter. På ett konto som fortfarande använder den hanterade konfigurationen är dessa uppgifter giltiga och avsändaren raderas, så att återansluta innebär att registrera den igen. På ett konto som har bytt till sitt eget Twilio kan raderingen inte autentiseras, och avsändaren förblir registrerad på det kontot – att återansluta innebär då bara att den befintliga avsändaren kopplas på igen.

### Lägg till ett nummer du redan äger (BYO)

```
POST /phone-numbers/byo
```

Hoppar helt över sök-och-köp-flödet ovan. Använd detta när kontot tar med sitt eget nummer (deras egen Twilio, deras eget Meta WhatsApp Business-konto eller en Android SMS-gateway) istället för att hyra ett via plattformen. Detta registrerar endast numret - inga krediter debiteras och ingenting tillhandahålls hos en leverantör här. Numret förblir inaktivt tills kontoinnehavaren slutför WhatsApp OAuth för att registrera en avsändare på det (samma flöde som instrumentpanelens "Bring your own number"-knapp startar).

| Fält | Krävs | Beskrivning |
|---|---|---|
| `phone_number` | Ja | Numret som ska läggas till, i E.164-format (t.ex. `+14155551234`). |
| `country_code` | Ja | ISO 3166-1 alpha-2 landskod (t.ex. `US`). |
| `display_name` | Nej | En vänlig etikett. Standard är telefonnumret. |
| `category` | Nej | Valfri kategorietikett. |

```bash
curl -X POST "https://api.youraiconnector.com/v1/phone-numbers/byo?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phone_number": "+14155551234",
    "country_code": "US",
    "display_name": "Support line"
  }'
```

**Svar** (`201 Created`):

```json
{
  "success": true,
  "phone_number": "+14155551234",
  "channel": "whatsapp",
  "type": "BYO",
  "whatsapp_status": "ADDED",
  "outgoing_status": "ADDED",
  "is_active": false
}
```

Ett `phone_number` som inte är ett riktigt E.164-nummer (eller som ser ut som Metas WhatsApp-testnummer, vilket aldrig kan skicka meddelanden till riktiga kunder) returnerar `400`. Att lägga till ett nummer som redan finns på kontot - även om det stavas något annorlunda, som Mexikos `+52` kontra `+521`-former - returnerar `409` istället för att skapa en dubblettrad.

### Ange ett nummer som primärt

```
POST /phone-numbers/{phoneNumber}/set-primary
```

Ändrar ett nummer till `is_active: true` och alla andra nummer på kontot till `is_active: false`, atomärt - kontot hamnar aldrig med två aktiva nummer, eller inga alls, mitt under en begäran. `is_active` kan avsiktligt inte ställas in via den allmänna uppdateringsslutpunkten; detta dedikerade anrop är det enda sättet att ändra vilket nummer som är primärt.

```bash
curl -X POST "https://api.youraiconnector.com/v1/phone-numbers/+14155551234/set-primary" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Svar**

```json
{
  "success": true,
  "phone_number": {
    "id": "+14155551234",
    "phone_number": "+14155551234",
    "display_name": "Support line",
    "channel": "whatsapp",
    "is_active": true,
    "whatsapp_status": "ONLINE"
  }
}
```

`phone_number` här är det fullständiga nummerobjektet (samma form som `GET /phone-numbers` returnerar), inte bara strängen. Ett `phoneNumber` som inte finns på kontot returnerar `404`.

### Ta bort ett nummers post (utan att frigöra det)

```
DELETE /phone-numbers/{phoneNumber}/record
```

En enkel borttagning av numrets post på detta konto - ingen frigöring eller avregistrering hos leverantören, och ingen 7-dagars nedkylningsperiod som frigöringssteget ovan tillämpas. Använd detta för att rensa bort BYO-, WhatsApp Web-, Telegram- eller LINE-poster, eller en inaktuell post, utan att gå igenom det hanterade frigöringsflödet. Till skillnad från en frigöring är borttagning av ett nummer som inte finns på kontot ett `404`, inte en tyst framgång.

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/phone-numbers/+14155551234/record" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Svar**

```json
{ "success": true, "phone_number": "+14155551234", "deleted": true }
```

---

## Dirigera en kanal till en kampanj

Att ansluta en kanal gör att meddelanden hamnar **i** kontot. Det avgör inte **vilken AI-agent som svarar på dem**.

Dirigering hanteras av **ingångspunkter** (Entry Points) på en AI-agent, inte av kampanjer. Varje kanal har en standardingångspunkt som anger vilken agent som svarar på nya, okända kontakter i den kanalen:

| Vad du vill göra | Anrop |
|---|---|
| Peka en kanal mot den agent som ska svara på den | `PUT /entry-points/channel-defaults` med brödtext `{ "channel": "instagram", "agent_id": "AGENT_ID" }` |
| Kontrollera om ingångspunkternas hierarki är aktiv för kontot | `GET /entry-points/routing-status`, som returnerar `{ "success": true, "cutover_enabled": true }` när ingångspunkterna avgör kontots dirigering |
| Lämna en kanal utan att någon agent svarar på den | `DELETE /entry-points/channel-defaults?channel=instagram` |

Tills en kanal har en startpunkt (Entry Point) lagras fortfarande det första meddelandet från någon du aldrig har pratat med, men ingenting hämtar det och ingen assistent svarar. Detta är steget som de flesta integrationer missar: att ansluta Instagram och skapa en agent räcker inte i sig självt — du måste också peka kanalen mot agenten. Den fullständiga uppsättningen anrop — inklusive en agent per WhatsApp-nummer, nyckelord och kommentarsregler — finns i [Entry Points API](entry-points.md).

`POST /channels/campaign` skriver fortfarande den äldre dirigeringskartan per kanal, dokumenterad nedan, men den kartan konsulteras inte längre för inkommande dirigering på något konto; den behålls endast för återställning. Bygg inte mot den.

### Dirigera en eller flera kanaler (äldre dirigeringskarta för kampanjer)

`POST /channels/campaign`

**Begäransfält**

| Fält | Krävs | Beskrivning |
|---|---|---|
| `campaign_id` | Ja | Den kampanj som ska svara på nya kontakter på dessa kanaler. Måste tillhöra kontot. |
| `channels` | Ja | En icke-tom array av kanaler att dirigera. Tillåtna: `whatsapp`, `whatsapp_web`, `telegram`, `instagram`, `messenger`, `chat_widget`, `custom_channel`, `sms`, `email`. |

Dirigeringsplatsen och kampanjens `enabled_channels`-lista uppdateras tillsammans i en atomär operation, så de kan aldrig hamna i otakt. En kanal som redan är dirigerad till en annan kampanj pekas helt enkelt om till denna.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/channels/campaign?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "campaign_id": "NBCXrhqGPSFsd6MV7pRo",
    "channels": ["instagram", "messenger"]
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/channels/campaign", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    campaign_id: "NBCXrhqGPSFsd6MV7pRo",
    channels: ["instagram", "messenger"],
  }),
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/channels/campaign",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "campaign_id": "NBCXrhqGPSFsd6MV7pRo",
        "channels": ["instagram", "messenger"],
    },
)
data = res.json()
```

**Svar**

```json
{
  "success": true,
  "campaign_id": "NBCXrhqGPSFsd6MV7pRo",
  "channels": ["instagram", "messenger"]
}
```

### Vad som måste vara uppfyllt för att dirigeringen faktiskt ska aktiveras

På ett konto som fortfarande läser den äldre dirigeringskartan för kampanjer lyckas dirigeringen som ett API-anrop, men tre saker i kampanjen avgör om ett faktiskt inkommande meddelande besvaras. Kontrollera alla tre när en dirigerad kanal förblir tyst.

| Krav | Vad som händer annars |
|---|---|
| `type` är `Incoming from Unknown Contacts` eller `Combined` | Begäran avvisas med `400`. Utgående kampanjer och nyckelordskampanjer kan inte inneha en dirigeringsplats. |
| `status` är `Live` | Dirigeringen lagras men plockar aldrig upp något. En `Draft`-kampanj är den vanligaste orsaken till "Jag dirigerade den men ingenting händer". |
| `ai_mode` är `true` | Kontakten skapas och meddelandet lagras, men assistenten svarar aldrig. |

Matchning av nyckelord finns nu på ingångspunkter — skapa en ingångspunkt av typen `keyword` på den AI-agent som ska svara.

### En kampanj per kanal

Varje kanal har exakt en äldre dirigeringsplats. Att dirigera en andra kampanj till samma kanal pekar tyst om platsen och returnerar `200` — det finns inget konfliktfel. Den tidigare kampanjen fortsätter att hantera de kontakter den redan har; den slutar bara ta emot nya.

### Rensa en kanals dirigering

`DELETE /channels/campaign/{channel}`

Tar bort dirigeringen för en enskild kanal, oavsett vilken kampanj den för närvarande pekar på, och tar bort kanalen från den kampanjens `enabled_channels`. Nya okända kontakter på kanalen plockas inte längre upp av någon kampanj. Kontakter som redan finns i kampanjen fortsätter som tidigare.

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/channels/campaign/instagram?apiKey=YOUR_API_KEY"
```

**Svar**

```json
{
  "success": true,
  "channel": "instagram",
  "cleared": true,
  "campaign_id": "NBCXrhqGPSFsd6MV7pRo"
}
```

Den är idempotent: att rensa en kanal som aldrig var dirigerad returnerar också `200`, med `cleared: false` och `campaign_id: null`. Denna slutpunkt kräver funktionen **inkommande kampanjer** i abonnemanget; utan den får du ett `403`.


---

## Använd din egen Meta-app (Instagram + Messenger)

Som standard körs Instagram + Messenger-anslutningen via plattformens Meta-app, så det är appens namn som kontoinnehavaren ser på Facebooks samtyckesskärm. Om du vill att samtyckesskärmen ska visa **ditt** varumärke istället kan du registrera en egen Meta-app och dirigera hela flödet genom den. När den väl är konfigurerad gäller den för ditt konto — ingenting ändras i anslutningsanropen ovan förutom varumärket.

> **Detta omfattar endast Instagram + Messenger.** WhatsApp, WhatsApp Web, Telegram och LINE-anslutningar påverkas inte av en anpassad Meta-app.

### Vad din app behöver först

Detta är den del som tar tid, och den sker helt och hållet på Metas sida:

1. **En app** av typen Business, med produkterna Messenger och Instagram tillagda.
2. **Avancerad åtkomst** (via Meta App Review) för: `pages_show_list`, `pages_messaging`, `pages_manage_metadata`, `pages_read_engagement`, `instagram_basic`, `instagram_manage_messages`. Utan avancerad åtkomst kan endast personer som har en roll i din app slutföra anslutningen — dina kunders anslutningar kommer att misslyckas. Appgranskning tar vanligtvis några veckor och kräver företagsverifiering.
3. **En Facebook-inloggning för företag-konfiguration** skapad i din app, som beviljar samma behörigheter. Dess numeriska konfigurations-ID är per app, så du måste skapa ditt eget.

Om din app saknar någon av de nödvändiga behörigheterna misslyckas anslutningen vid anslutningstillfället med ett tydligt felmeddelande som anger vad som saknas (synligt i `/status`-avsökningen som `byo_app_missing_permissions`) — istället för att verka fungera och sedan misslyckas vid det första meddelandet.

### Steg 1 - Spara din app

`PUT /account-config/meta-app`

| Fält | Krävs | Beskrivning |
|---|---|---|
| `app_id` | Ja | Ditt Meta-app-ID (Inställningar → Grundläggande). |
| `app_secret` | Ja | Din Meta-apphemlighet. Verifieras mot Meta innan den lagras, och krypteras sedan. Returneras aldrig av någon slutpunkt. |
| `config_id` | Ja | Det numeriska ID:t för Facebook-inloggning för företag-konfigurationen i din app. |

Alla tre krävs för Facebook-inloggningsflödet. Om du bara kör push-kanalen för Instagram-inloggningstoken som beskrivs längre ner, kan du utelämna dem helt.

```bash
curl -X PUT "https://api.youraiconnector.com/v1/account-config/meta-app?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "app_id": "1234567890123456",
    "app_secret": "your-app-secret",
    "config_id": "9876543210987654"
  }'
```

**Svar**

```json
{
  "success": true,
  "app_id": "1234567890123456",
  "config_id": "9876543210987654",
  "verify_token": "1f4c…a9",
  "webhook_urls": {
    "instagram": "https://api.youraiconnector.com/v1/incoming-instagram-message/byo/YOUR_ACCOUNT_ID",
    "messenger": "https://api.youraiconnector.com/v1/incoming-messenger-message/byo/YOUR_ACCOUNT_ID"
  }
}
```

### Steg 2 - Konfigurera din app för att kommunicera med oss

I din Meta-apps instrumentpanel:

1. **Webhooks** - för både Instagram- och Messenger-produkterna, ställ in Callback URL till motsvarande `webhook_urls`-värde från svaret, och Verify token till `verify_token`. Prenumerera på fälten `messages`, `messaging_postbacks` och `comments`.
2. **Giltiga OAuth-omdirigerings-URI:er** - lägg till `https://api.youraiconnector.com/v1/auth-meta-callback-handler` så att samtyckesflödet kan återvända.

`GET /account-config/meta-app` returnerar samma konfigurationsmaterial varje gång; `DELETE /account-config/meta-app` tar bort appen (framtida anslutningar återgår till plattformsappen — ta även bort webhook-prenumerationen i din app).

### Steg 3 - Anslut som vanligt

Ingenting annat ändras. `POST /channels/meta/connect` (och den värdbaserade `connect_url`-sidan) använder automatiskt din app för ditt konto; svarets `uses_byo_meta_app: true` bekräftar vilken app samtyckesskärmen kommer att visa. Meddelandesändning, val av sida och frånkopplingar fungerar identiskt.

## Använd din egen Instagram-inloggningsapp (token-push)

Avsnittet ovan täcker Facebook-inloggningsflödet, där kontot ansluts via en Facebook-sida. Meta erbjuder även **Instagram API med Instagram-inloggning** (Business Login for Instagram): kontoinnehavaren autentiserar sig direkt på Instagram, utan att något Facebook-konto eller någon Facebook-sida krävs.

Om din plattform redan kör en egen Meta-app med den produkten behöver du inte använda något OAuth-flöde från vår sida alls. Dina klienter auktoriserar **din** app, och du skickar (push) den färdiga autentiseringsuppgiften per konto till oss:

1. Du sparar din Instagram-apps autentiseringsuppgifter en gång (så att vi kan verifiera dina webhooks).
2. Per konto skickar du Instagram-proffskontots ID + den långlivade Instagram-användartoken som din app har erhållit.
3. Du pekar din apps Instagram-meddelande-webhook mot oss. Händelser för konton som du aldrig har skickat bekräftas och ignoreras.
4. Du äger token-livscykeln: uppdatera tokens i ditt eget system och skicka varje uppdaterad token med samma anrop. Vi uppdaterar aldrig en skickad token.

### Vad din app behöver först

- Produkten **Instagram** ("API setup with Instagram login") tillagd i din Meta-app. Den produkten har sitt **eget App ID och App Secret-par**, separat från Facebooks App ID/Secret — du hittar dem i produktens inställningspanel.
- **Advanced Access** (via Meta App Review) för `instagram_business_basic` och `instagram_business_manage_messages` (lägg till `instagram_business_manage_comments` om du använder kommentarsautomatiseringar). Utan detta kan endast personer med en roll i din app auktorisera den.

### Steg 1 - Spara dina Instagram-appuppgifter

Samma slutpunkt som ovan — skicka Instagram-paret till `PUT /account-config/meta-app`. Facebook-fälten behövs inte för denna kanal: skicka paret för sig om du bara kör Instagram-inloggning, eller tillsammans med Facebook-fälten om du kör båda. En sparåtgärd beskriver alltid hela inställningen, så den uppsättning du utelämnar tas bort.

| Fält | Obligatoriskt | Beskrivning |
|---|---|---|
| `instagram_app_id` | Tillsammans | Instagram-produktens eget numeriska App ID (inte Facebooks App ID). |
| `instagram_app_secret` | Tillsammans | Instagram-produktens egen App Secret. Krypterad vid lagring, returneras aldrig. |

```bash
curl -X PUT "https://api.youraiconnector.com/v1/account-config/meta-app?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "instagram_app_id": "1122334455667788",
    "instagram_app_secret": "your-instagram-app-secret"
  }'
```

**Svar** — innehåller webhook-URL:en för Instagram-inloggning (URL:erna `instagram` och `messenger` visas endast när även Facebook-fälten lagras):

```json
{
  "success": true,
  "instagram_app_id": "1122334455667788",
  "verify_token": "1f4c…a9",
  "webhook_urls": {
    "instagram_login": "https://api.youraiconnector.com/v1/incoming-instagram-login-message/byo/YOUR_ACCOUNT_ID"
  }
}
```

I din apps **Webhooks**-panel för Instagram-produkten, ställ in Callback URL till `webhook_urls.instagram_login`, Verify token till `verify_token`, och prenumerera på fälten `messages` och `comments`.

### Steg 2 - Skicka (push) en token per konto

`PUT /channels/instagram-login/token`

Fungerar med `sub_account_id` precis som alla andra rutter, så en byrånivånyckel kan provisionera hela sin flotta.

| Fält | Obligatoriskt | Beskrivning |
|---|---|---|
| `ig_user_id` | Ja | **Instagram-proffskontots ID** — fältet `user_id` från `GET https://graph.instagram.com/v21.0/me?fields=user_id,username`. Detta är samma ID som Instagram-webhooks bär som `entry.id`. ⚠️ Det är **inte** fältet `id` från `/me` — det är app-scopat och skiljer sig åt per Meta-app. Att skicka det app-scopade ID:t returnerar ett `400` som anger felet. |
| `access_token` | Ja | Den långlivade Instagram-användartoken som din app har erhållit för det kontot. Valideras live mot Instagram innan den lagras: token måste fungera och måste tillhöra `ig_user_id`. |
| `expires_at` | Nej | ISO-8601-utgångsdatum för token. Alternativt skicka `expires_in` (sekunder). Standard är 60 dagar. |
| `username` | Nej | Kontots @handle; vi läser det från Instagram ändå. |

```bash
curl -X PUT "https://api.youraiconnector.com/v1/channels/instagram-login/token?apiKey=YOUR_AGENCY_KEY&sub_account_id=CLIENT_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "ig_user_id": "17841400000000000",
    "access_token": "IGAAR…",
    "expires_at": "2026-11-01T00:00:00Z"
  }'
```

**Svar**

```json
{
  "success": true,
  "ig_user_id": "17841400000000000",
  "username": "acme.studio",
  "expires_at": "2026-11-01T00:00:00.000Z",
  "webhook_url": "https://api.youraiconnector.com/v1/incoming-instagram-login-message/byo/YOUR_ACCOUNT_ID"
}
```

Som en del av push-åtgärden prenumererar vi din app på det kontots webhooks (`subscribed_apps` med den skickade token), så att meddelanden börjar flöda utan att du behöver göra något extra anrop.

**Uppdatering** - skicka den uppdaterade token till samma slutpunkt med samma `ig_user_id`; den uppdaterar den lagrade token och utgångsdatumet på plats.

**Konflikter** - ett Instagram-konto kan aldrig vara aktivt på två anslutningar samtidigt. Om kontot redan är anslutet någon annanstans, eller på detta specifika konto via Facebook-sidans flöde, returnerar push-meddelandet en `409` som talar om vilken anslutning som måste kopplas bort först. En anslutning via Facebook-flödet ersätts aldrig automatiskt, eftersom den även kan användas för Messenger.

### Steg 3 - Koppla från när en klient lämnar

`DELETE /channels/instagram-login/token` (samma autentisering och `sub_account_id`) avregistrerar webhooks så gott det går och tar bort den lagrade autentiseringsuppgiften. Det lyckas alltid, även när token redan har löpt ut — och när autentiseringsuppgiften väl är borta ignoreras det kontots webhook-händelser.

---

## Tips för att bygga en pålitlig wrapper

- **Polla försiktigt.** Några sekunder räcker gott. Stoppa när du når ett terminalt tillstånd (`connected` / `ONLINE`, eller en felstatus), och sätt en rimlig total timeout för loopen (webbläsar-/QR-stegen löper ut, se varje `expires_at`).
- **URL-koda telefonnummer i sökvägen.** Det inledande `+` bör skickas som `%2B`. Slutpunkterna återställer även nakna siffror, men kodning är det säkra standardvalet.
- **Förvänta dig aldrig att hemligheter returneras.** Åtkomsttoken, kanalhemligheter och sidtoken accepteras eller lagras men returneras aldrig i något svar.
- **Hantera autentiseringsspärren.** Ett `403` innebär att API-åtkomst inte ingår i planen, eller att kanalen du ansluter inte ingår i kontots plan. Se [API-åtkomst](../integrations/api-access.md).
- **Tänk på hastighetsbegränsningen.** Autentiserade förfrågningar är begränsade till 300 per minut; ett `429` innebär att du bör vänta och försöka igen. Se [Autentisering](authentication.md).

## Nästa steg

- [Autentisering](authentication.md) - de fyra accepterade autentiseringsformerna och felformatet.
- [API-åtkomst](../integrations/api-access.md) - generering och hantering av din API-nyckel.
