
# API de conectare a canalelor

Acest ghid vă arată cum să conectați canalele de mesagerie la un cont folosind API-ul. Este scris pentru un dezvoltator care construiește o integrare sau un wrapper, așa că se concentrează pe cererile exacte, ordinea în care trebuie făcute și răspunsurile pe care le primiți.

Există un tipar pe care trebuie să îl înțelegeți de la început, deoarece se aplică aproape fiecărui canal de aici.

## Tiparul de conectare urmată de interogare (poll)

Majoritatea canalelor nu pot fi conectate printr-un singur apel API. Conectarea WhatsApp, Instagram sau Messenger înseamnă că titularul contului trebuie să se conecteze la propriul cont de furnizor și să aprobe accesul. **Nu există o cale headless (complet automatizată)** pentru acea aprobare - o persoană reală trebuie să deschidă un URL într-un browser sau să scaneze un cod QR cu telefonul.

Așadar, fluxul este întotdeauna:

1. **Inițiați conexiunea** cu un `POST`. Răspunsul vă oferă fie un URL de deschis, fie un cod QR de afișat.
2. **Transmiteți acest lucru utilizatorului final** - deschideți URL-ul în browserul său sau afișați codul QR pe ecran pentru ca acesta să îl scaneze.
3. **Interogați endpoint-ul de stare** cu `GET` la un interval scurt (la fiecare câteva secunde) până când starea ajunge la una de conectat.

Sarcina integrării dvs. este să conduceți acea buclă: afișați URL-ul sau codul QR, apoi interogați până la finalizare. Planificați-vă interfața în jurul interogării - un indicator de încărcare cu un mesaj de tipul „așteptăm să finalizați în browser” funcționează bine.

::: note
**Notă:** Înainte de a începe, asigurați-vă că accesul API este activat în planul dumneavoastră și că aveți o cheie API. Consultați [Acces API](../integrations/api-access.md) pentru a afla cum să generați una. Toate cererile de mai jos utilizează URL-ul de bază `https://api.youraiconnector.com/v1` și trebuie să autentificați fiecare cerere. Consultați [Autentificare](authentication.md) pentru cele patru forme acceptate - exemplele de aici utilizează antetul `X-API-Key`, cu un exemplu cURL pe pagină care arată forma de interogare mai simplă `?apiKey=`.
:::


---

## Instagram + Messenger (Meta)

Instagram și Messenger sunt conectate împreună într-un singur flux, deoarece ambele rulează pe o pagină de Facebook. Titularul contului autorizează prin Facebook, dvs. preluați lista de pagini pe care le administrează și alegeți ce pagină să conectați.

### Pasul 1 - Inițiază conexiunea Instagram + Messenger

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

Aceasta returnează un URL de consimțământ. Nu sunt trimise credențiale în această cerere - conexiunea este autorizată în întregime în browser.

**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.
```

**Răspuns**

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

Deschideți `oauth_url` în browserul utilizatorului final pentru ca acesta să se poată conecta la Facebook și să aprobe accesul. Încercarea de conectare expiră la `expires_at` (aproximativ 30 de minute) - dacă expiră, luați-o de la capăt. Tratați `state_token` ca pe un secret cu durată scurtă de viață și nu îl înregistrați în log-uri.

### Cea mai simplă opțiune pentru Instagram + Messenger: predarea `connect_url`

Răspunsul include, de asemenea, o pagină `connect_url` gata de utilizare: o pagină găzduită care rulează întregul flux pentru titularul contului. Aceștia o deschid, se conectează la Facebook, iar când au mai mult de o pagină, aceasta afișează lista și le permite să aleagă pe care să o conecteze - apoi raportează succesul de la sine. Oferiți acest link titularului contului în loc să deschideți singur `oauth_url`, să construiți un selector de pagini și să interogați starea. Linkul funcționează timp de aproximativ 30 de minute (`connect_url_expires_at`); dacă expiră, începeți o nouă conexiune. Pașii manuali de mai jos sunt pentru integrările care doresc să gestioneze fluxul și să redea singure selectorul de pagini.

### Pasul 2 - Interogați starea până la încărcarea paginilor

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

După ce utilizatorul finalizează autentificarea prin Facebook, interogați acest endpoint la fiecare câteva secunde. Câmpul `status` parcurge acești pași:

| `status` | Semnificație |
|---|---|
| `pending` | Consimțământul nu a fost încă finalizat. Continuați să așteptați. |
| `token_received` | Autorizat, dar lista de pagini încă se încarcă. |
| `pages_loaded` | Paginile sunt disponibile - treceți la pasul 3. |
| `connected` | O pagină a fost selectată și canalul este activ. |

**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".
```

**Răspuns (după ce paginile s-au încărcat)**

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

### Pasul 3 - Listați paginile (opțional)

Dacă preferați să preluați lista de pagini separat (de exemplu, pentru a afișa un selector), utilizați:

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

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

Returnează același tablou `pages` ca și endpoint-ul de stare. (Endpoint-ul `status` include deja paginile, deci acest apel este doar pentru comoditate.)

### Pasul 4 - Selectați pagina pentru conectare

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

Trimiteți `page_id` paginii alese de utilizator. Contul de Instagram conectat la acea pagină este conectat automat; aveți nevoie de obiectul `instagram` doar dacă doriți să suprascrieți contul de Instagram utilizat.

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

**Răspuns**

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

Canalul este acum conectat. Un `GET /channels/meta/status` ulterior va raporta `status: "connected"`.

### Listează postările paginii conectate

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

Returnează postările recente ale paginii pe care ați conectat-o - conținut Instagram sau postări Facebook. Acesta este elementul din care redați un selector atunci când configurați un Punct de Intrare care reacționează la comentariile de la o anumită postare.

| Parametru de interogare | Obligatoriu | Descriere |
|---|---|---|
| `platform` | Da | `instagram` sau `facebook`. Orice altceva returnează o `400`. |
| `limit` | Nu | Câte postări să fie returnate, `1`-`50`. Valoarea implicită este `25`. |
| `after` | Nu | Cursor pentru pagina următoare - transmiteți valoarea `nextCursor` din răspunsul anterior. |

**cURL**

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

**Răspuns**

```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` este eticheta proprie Instagram (`REELS`, `FEED`, `STORY` sau formatul - `IMAGE`, `VIDEO`, `CAROUSEL_ALBUM`); pentru Facebook este întotdeauna `POST`. `nextCursor` este `null` pe ultima pagină.

Dacă nu poate fi listat nimic, apelul returnează totuși `200` cu `connected: false` și un tablou `posts` gol, plus un `reason` care vă explică motivul:

| `reason` | Ce trebuie făcut |
|---|---|
| _(absent)_ | Nicio pagină nu este conectată încă - rulați mai întâi fluxul de conectare. |
| `no_instagram_account` | O pagină de Facebook este conectată, dar niciun cont de business Instagram nu este legat de aceasta. Postările de Facebook se listează în continuare corect. |
| `token_expired` | Credențialele paginii stocate nu mai funcționează - reconectați canalul. |

### Deconectează Instagram + Messenger

```
DELETE /channels/meta
```

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

**Răspuns**

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

Aceasta oprește rutarea primită atât pentru Instagram, cât și pentru Messenger. Este idempotentă - apelarea acesteia când nimic nu este conectat va reuși în continuare.

---

## WhatsApp Business

Aceasta conectează un număr oficial WhatsApp Business. Numărul trebuie să existe deja în cont înainte de a apela funcția de conectare. La fel ca la Meta, titularul contului autorizează în browserul său, apoi interogați până când numărul raportează `ONLINE`.

### Pasul 1 - Inițiază conexiunea WhatsApp Business

```
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.
```

| Câmp | Obligatoriu | Descriere |
|---|---|---|
| `phone_number` | Da | Numărul de conectat, în format E.164 (de ex. `+14155551234`). |
| `only_waba_sharing` | Nu | Restricționează autorizarea la partajarea unui cont WhatsApp Business existent, sărind peste configurarea unui nou expeditor. Valoarea implicită este `false`. |
| `retry` | Nu | Rulează din nou autorizarea pentru un număr a cărui încercare anterioară nu s-a finalizat. Valoarea implicită este `false`. |
| `business_name` | Nu | Suprascriere cosmetică pentru numele afacerii afișat doar pe ecranul de consimțământ (max 256 caractere). Nu este stocat. |
| `description` | Nu | Suprascriere cosmetică pentru descrierea afacerii afișată doar pe ecranul de consimțământ (max 256 caractere). Nu este stocat. |

**Răspuns**

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

Deschideți `oauth_url` în browserul titularului contului pentru a autoriza. Odată ce aceștia aprobă, înregistrarea se finalizează în fundal.

### Pasul 2 - Interogați starea până când este ONLINE

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

Interogați acest lucru până când `status` este `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".
```

**Răspuns**

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

Câmpul `status` poate fi:

| `status` | Semnificație |
|---|---|
| `PENDING` | Autorizat, aprobarea este încă în curs. Continuați interogarea. |
| `ONLINE` | Conectat și gata de trimitere. |
| `RATE_LIMITED` | Prea multe încercări - așteptați înainte de a reîncerca. |
| `REGISTRATION_FAILED` | Configurarea nu a putut fi finalizată. |
| `DELETED` | Înregistrarea nu mai există. |

`live: true` înseamnă că starea a fost verificată în raport cu furnizorul în timp real; `false` înseamnă că provine din ultima stare stocată în cache.

### Deconectează un număr WhatsApp Business

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

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

**Răspuns**

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

Numărul în sine rămâne în cont, astfel încât să îl puteți reconecta ulterior.

---

## WhatsApp Web

WhatsApp Web conectează un număr obișnuit de WhatsApp prin scanarea unui cod QR, exact ca la conectarea unui dispozitiv în aplicația WhatsApp. Fluxul este: pornește sesiunea, preia codul QR și afișează-l, apoi interoghează starea până când aceasta este `connected`.

### Pasul 1 - Inițiază o sesiune de asociere WhatsApp Web

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

| Câmp | Obligatoriu | Descriere |
|---|---|---|
| `phone_number` | Da | Numărul de WhatsApp care trebuie conectat, în format E.164. |
| `proxy_country` | Nu | Codul de țară ISO 3166-1 alpha-2 pentru regiunea de rutare. Detectat automat din număr dacă este omis. |
| `force_new` | Nu | Elimină orice sesiune existentă și începe o asociere nouă. Valoarea implicită este `false`. |
| `import_contacts` | Nu | Importă contactele existente ale dispozitivului la prima conectare. Valoarea implicită este `false`. |
| `pause_ai_for_imported_contacts` | Nu | La importarea contactelor, menține răspunsurile automate întrerupte pentru acestea. Valoarea implicită este `true`. |
| `import_existing_chats` | Nu | Importă istoricul conversațiilor existente (necesită `import_contacts: true`). Valoarea implicită este `false`. |

**Răspuns**

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

### Cea mai simplă opțiune pentru WhatsApp Web: predarea `connect_url`

Răspunsul include un `connect_url` gata de utilizare: o pagină găzduită care afișează codul QR, îl reîmprospătează automat pe măsură ce se rotește și trece la un mesaj de succes în momentul în care numărul este conectat. Pur și simplu oferiți acest link titularului contului (deschideți-l într-un browser, trimiteți-l acestuia sau afișați-l ca un cod QR/buton) și rugați-l să îl scaneze cu WhatsApp - nu trebuie să preluați codul QR sau să interogați nimic pe cont propriu. Linkul funcționează timp de aproximativ 30 de minute (`connect_url_expires_at`); dacă expiră înainte ca aceștia să termine, începeți o nouă conexiune pentru a obține unul nou.

Aceasta este calea recomandată atunci când o persoană poate deschide un link. Pașii manuali de mai jos (preluarea codului QR de către dvs., interogarea stării) sunt destinați integrărilor care doresc să redea codul QR în propria interfață.

Răspunsul vă oferă, de asemenea, `poll_qr_path` și `poll_status_path` exacte pe care să le utilizați, astfel încât să nu fie nevoie să le construiți singur.

### Pasul 2 - Preluarea și afișarea codului QR

```
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.
```

**Răspuns**

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

Redă codul QR pentru ca utilizatorul să îl scaneze cu telefonul (WhatsApp > Dispozitive conectate > Conectează un dispozitiv):

- `qr_data_url` este o imagine gata de utilizare - insereaz-o direct într-un `<img src>`.
- `qr_code` este sarcina utilă brută (raw payload) dacă preferi să generezi singur imaginea.

Codul QR are o durată de viață scurtă. Dacă apelezi acest lucru imediat după pornirea sesiunii, este posibil să primești un `404` cu mesajul "QR code not available yet" - așteaptă puțin și reîncearcă. Dacă primești un `410` ("QR code expired"), reia conexiunea de la început pentru a obține un cod nou.

### Pasul 3 - Interogarea stării până la conectare

```
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").
```

**Răspuns**

```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` | Semnificație |
|---|---|
| `not_initialized` | Nu există încă o sesiune (eroare terminală). |
| `qr_pending` | Se așteaptă scanarea codului QR. |
| `connecting` | Scanat, se finalizează configurarea. |
| `connected` / `open` | Conectat și activ - aceasta este reușita. |
| `disconnected` | Sesiune încheiată (eroare terminală). |

### Deconectează o sesiune WhatsApp Web

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

**Răspuns**

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

Aceasta deconectează dispozitivul și elimină conexiunea. Curăță întotdeauna starea locală, deci este idempotentă chiar dacă sesiunea subiacentă a fost deja eliminată.

---

## Telegram

> **Disponibilitate:** Telegram se conectează la fel ca orice alt canal și este deschis pentru fiecare cont — nu este necesar să fie activat pentru tine. Punctele finale Telegram de mai jos pot returna în continuare `403` dacă Telegram nu este inclus în planul contului, caz în care eroarea va fi `"This channel is not included in your current plan. Upgrade to unlock it."`.

Telegram conectează un cont personal prin număr de telefon plus un cod de autentificare unic (și o parolă cu doi factori, dacă contul are una setată). Fluxul este: porniți sesiunea, trimiteți codul, trimiteți opțional parola, apoi confirmați prin stare.

### Pasul 1 - Inițiază o sesiune de conexiune Telegram

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

| Câmp | Obligatoriu | Descriere |
|---|---|---|
| `phone_number` | Da | Numărul de telefon al contului pentru conectare, în format E.164. |
| `mode` | Nu | `code` (implicit) trimite un cod de autentificare unic către cont; `qr` returnează un jeton de autentificare și un URL QR pentru afișare. |
| `proxy_country` | Nu | Codul de țară ISO 3166-1 alpha-2 pentru ruta rețelei de ieșire. |
| `force_new` | Nu | Când este `true`, elimină orice sesiune existentă și începe de la zero. |

**Răspuns**

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

În modul `code`, contul primește un cod de autentificare în Telegram, iar `status` este `code_required`. (În modul `qr`, răspunsul include, de asemenea, `login_token` și `qr_url` pentru afișare în vederea scanării, iar `status` este `qr_required`.)

### Cea mai simplă opțiune pentru Telegram: predarea `connect_url`

Răspunsul include un `connect_url` gata de utilizare: o pagină găzduită care finalizează conexiunea de la sine. În modul `code`, titularul contului introduce codul de autentificare - și o parolă de verificare în doi pași, dacă contul are una. În modul `qr`, pagina afișează un cod QR care se actualizează automat pentru a fi scanat din aplicația Telegram. În ambele cazuri, pagina raportează succesul automat, așa că puteți pur și simplu să oferiți acest link titularului contului în loc să vă construiți propria interfață și să interogați starea. Linkul este valabil aproximativ 30 de minute (`connect_url_expires_at`); dacă expiră, începeți o conexiune nouă pentru a obține unul proaspăt.

Pașii manuali de mai jos (colectarea codului de către dvs., trimiterea acestuia, interogarea stării; sau randarea `qr_url` și interogarea) sunt destinați integrărilor care doresc să își randeze singure interfața.

### Pasul 2 - Trimiterea codului de autentificare

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

**Răspuns**

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

Dacă `status` este `connected`, ați terminat. Dacă contul are activată autentificarea cu doi factori, `status` va fi `password_required` - treceți la pasul 3.

### Pasul 3 - Trimiterea parolei cu doi factori (doar dacă este necesar)

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

Apelați acest pas doar când pasul 2 a returnat `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()
```

**Răspuns**

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

### Verifică starea Telegram

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

**Răspuns**

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

`status` poate fi `connected`, `code_required`, `password_required`, `initializing`, `disconnected`, `not_initialized` sau `error`.

### Deconectează Telegram

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

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

**Răspuns**

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

Idempotent - apelurile repetate reușesc.

---

## Instagram (cont personal)

> Versiune beta cu disponibilitate limitată, activată per cont. Aceasta conectează un cont personal de Instagram prin autentificarea cu nume de utilizator și parolă (nu prin API-ul oficial Business). Dacă contul nu este activat pentru versiunea beta, apelul de conectare returnează o eroare de permisiune.

Deoarece acest lucru necesită propria autentificare Instagram a titularului contului, cea mai simplă cale este să le oferiți pagina găzduită `connect_url` și să îi lăsați să își introducă credențialele acolo - integrarea dvs. nu gestionează niciodată parola.

### Pasul 1 - Inițiază o conexiune Instagram (personal)

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

Trimiteți `username` și `password` pentru Instagram.

**Răspuns**

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

Dacă contul are autentificare cu doi factori sau Instagram prezintă un punct de verificare, `status` revine ca `two_factor_required` sau `challenge_required` - trimiteți codul către `/connect/{id}/verify-2fa` sau `/connect/{id}/verify-challenge` de mai jos, apoi interogați `/connect/{id}/status` până când `connected`. `{id}` este numele de utilizator Instagram normalizat returnat ca `account_id`/`username` în răspunsul de mai sus - utilizați-l la fiecare pas de mai jos.

### Pasul 2 - Trimiteți codul de autentificare cu doi factori (dacă este solicitat)

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

Apelați acest lucru doar atunci când pasul 1 (sau pasul 3) a returnat `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" }'
```

**Răspuns**

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

`status` poate reveni ca `connected` (finalizat), `two_factor_required` (cod greșit, încercați din nou) sau `challenge_required` (Instagram solicită și un cod de verificare - mergeți la pasul 3).

### Pasul 3 - Trimiteți codul de confirmare a punctului de verificare (dacă este solicitat)

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

Apelați acest lucru doar atunci când un pas anterior a returnat `challenge_required`. Aceeași formă de cerere și răspuns ca la pasul 2 de mai sus.

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

### Verificați starea Instagram (personal)

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

Interogați acest lucru până când `status` este `connected` sau până când raportează o eroare terminală.

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

**Răspuns**

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

`status` poate fi `connected`, `two_factor_required`, `challenge_required`, `initializing`, `disconnected`, `not_initialized` sau `error`. `live: true` înseamnă că aceasta a fost citită în direct de la worker-ul de conexiune, în loc de o valoare memorată în cache.

### Cea mai simplă opțiune pentru Instagram (personal): predarea `connect_url`

Răspunsul include un `connect_url`: o pagină găzduită unde titularul contului își introduce numele de utilizator și parola de Instagram (precum și un cod 2FA sau de verificare dacă Instagram solicită unul), care raportează succesul de la sine. Credențialele merg direct la Instagram și nu sunt stocate. Oferiți acest link titularului contului în loc să colectați parola acestuia în propria interfață. Linkul funcționează timp de aproximativ 30 de minute (`connect_url_expires_at`).

### Deconectare Instagram (personal)

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

Idempotent - apelurile repetate reușesc.

### Sincronizarea urmăritorilor

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

Declanșează manual o sincronizare a urmăritorilor pentru un cont conectat - aceeași sarcină care rulează automat în fundal, expusă aici pentru o acțiune de tip „Reîmprospătare urmăritori” la cerere. Aceasta preia lista actuală de urmăritori a contului, înregistrează persoanele noi și (atunci când o campanie Live are activată funcția de contactare a urmăritorilor) trimite noilor urmăritori un mesaj direct de întâmpinare, până la o limită zilnică.

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

**Răspuns**

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

> Aceste cinci câmpuri sunt singurul loc de pe această pagină care returnează `camelCase` în loc de `snake_case` - așa este configurat acest endpoint în prezent, nu este o greșeală de tipar. `isBaselineSeed: true` înseamnă că aceasta a fost prima sincronizare după conectare, care doar înregistrează lista inițială de urmăritori și nu trimite niciodată mesaje directe de contactare (deci `dmsSent` este întotdeauna `0` la acea rulare).

Prima apelare pentru un cont poate dura ceva timp (parcurgerea întregii liste de urmăritori); apelările ulterioare sunt mai rapide, deoarece sunt procesate doar diferențele pentru noii urmăritori. `404` înseamnă că contul nu este conectat; `412` înseamnă că inițializarea conexiunii nu s-a finalizat încă - așteptați și reîncercați.

---

## LINE

LINE este cel mai simplu canal de conectat deoarece nu există nicio redirecționare prin browser sau interogare (polling). Clientul creează un canal Messaging API în consola LINE Developers, copiază două valori, iar tu le trimiți într-un singur apel. Apoi le oferi înapoi un URL de webhook pe care să îl lipească în consolă.

### Pasul 1 - Conectarea cu credențialele canalului

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

| Câmp | Obligatoriu | Descriere |
|---|---|---|
| `channel_access_token` | Da | Tokenul de acces pe termen lung al canalului Messaging API al Contului Oficial. Folosit pentru a trimite și primi mesaje. |
| `channel_secret` | Da | Secretul canalului Messaging API, folosit pentru a verifica semnăturile evenimentelor primite. |
| `channel_id` | Nu | ID-ul numeric al canalului. Doar informativ. |

**Răspuns**

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

Două câmpuri contează pentru ceea ce faci în continuare:

- **`webhook_url`** - clientul trebuie să lipească acest lucru în câmpul **Webhook URL** al canalului său LINE din consola LINE Developers (și să activeze "Use webhook"). Până când nu fac acest lucru, nu vor sosi mesaje primite. Arată-le acest lucru în mod vizibil.
- **`chat_mode_ok`** - când `false`, Contul Oficial este în modul "chat" și nu va primi sau trimite mesaje până când nu este comutat în modul "bot" în LINE Official Account Manager. Condiționează procesul de onboarding de acest indicator și spune-i clientului să schimbe modul.

> `channel_access_token` și `channel_secret` nu sunt returnate niciodată de niciun endpoint. Stochează-le de partea ta dacă ai nevoie de ele din nou; în caz contrar, lipește-le din nou din consola LINE.

`bot_user_id` returnat aici este identificatorul de conexiune pe care îl folosești în apelurile de stare, verificare și deconectare de mai jos.

### Pasul 2 - Reverificarea după configurarea webhook-ului

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

După ce clientul termină configurarea URL-ului webhook și trece la modul bot, apelați această funcție pentru a revalida tokenul stocat și a reîmprospăta modul de chat stocat în cache.

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

**Răspuns**

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

Dacă `token_valid` este `false`, tokenul de acces stocat nu mai autentifică - solicitați clientului să îl emită din nou în consolă și apelați `POST /channels/line` din nou cu noul token.

### Verificarea stării LINE

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

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

**Răspuns**

```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 nu are un flux de stare live, deci `live` este întotdeauna `false` aici - valorile reflectă starea capturată la momentul conectării (sau al ultimei verificări).

### Deconectare LINE

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

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

**Răspuns**

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

---

## Viber

Viber se conectează în același mod ca LINE - lipiți tokenul de autentificare al botului din Panoul de Administrare Viber într-un singur apel - cu o diferență importantă: conectarea ÎNREGISTREAZĂ totodată webhook-ul nostru pe botul dvs. în acel moment, deci nu există un pas separat în consolă ulterior. Acest lucru înseamnă, de asemenea, că o încercare de conectare poate eșua dacă sistemul nostru de intrare nu poate răspunde la verificarea sincronă a webhook-ului Viber, nu doar dacă tokenul în sine este incorect.

### Pasul 1 - Conectați-vă cu tokenul de autentificare al botului

```
POST /channels/viber
```

| Câmp | Obligatoriu | Descriere |
|---|---|---|
| `auth_token` | Da | Tokenul de autentificare al botului, din Panoul de Administrare Viber (Setările botului meu). |

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

**Răspuns**

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

Tokenul de autentificare nu este niciodată returnat de niciun endpoint - stocați-l în partea dvs. dacă va trebui să îl lipiți din nou. `bot_id` este identificatorul de conexiune utilizat de apelurile de stare, verificare și deconectare de mai jos.

### Verificarea stării Viber

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

Raportează starea conexiunii stocate. Adăugați `?live=true` pentru a verifica din nou botul față de Viber și a reîmprospăta înregistrarea webhook-ului stocată în cache - util înainte de a presupune că un bot silențios este într-adevăr defect.

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

**Răspuns**

```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` înseamnă că webhook-ul botului nu mai indică spre noi - mesajele primite sunt pierdute. Acest lucru înseamnă de obicei că un alt instrument a conectat același bot ulterior (înregistrarea webhook-ului Viber funcționează pe principiul „ultima scriere câștigă”). Remediați problema cu apelul de reverificare de mai jos, fără a fi nevoie să cereți clientului să lipească din nou tokenul. `live` este `false` atunci când răspunsul este ultima stare stocată în cache, în loc de o verificare proaspătă față de Viber.

### Reînregistrarea webhook-ului

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

Acțiunea de reparare pentru `webhook_ok: false` - reînregistrează webhook-ul nostru pe bot folosind tokenul de autentificare deja stocat.

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

**Răspuns**

```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` înseamnă că tokenul stocat nu mai funcționează - reconectați-vă cu `POST /channels/viber` și un token nou.

### Deconectare Viber

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

Anulează înregistrarea webhook-ului nostru de partea Viber (best-effort) și elimină conexiunea.

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

**Răspuns**

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

---

## TikTok

> **Disponibilitate:** Versiune beta cu disponibilitate limitată, activată per cont. Conectarea TikTok returnează o eroare de permisiune până când contul este activat pentru aceasta.

TikTok Business Messaging este un canal OAuth complet, similar cu Meta, dar mai simplu în ceea ce privește interogarea (polling): nu există un pas dedicat de interogare a stării pentru implementare, deoarece contul conectat apare de la sine odată ce TikTok redirecționează înapoi și conexiunea este scrisă. Endpoint-ul de stare de mai jos există pentru confirmarea stării la cerere (instrumente de asistență, verificări de sănătate), nu ca ceva pe care trebuie să îl rulați în buclă în timpul conectării.

### Pasul 1 - Inițierea conexiunii TikTok

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

Nu necesită credențiale - titularul contului autorizează totul direct în browserul său.

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

**Răspuns**

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

Deschideți `oauth_url` în browserul titularului contului pentru ca acesta să se poată autentifica în TikTok și să aprobe accesul. Starea expiră la `expires_at` (aproximativ 30 de minute) - dacă expiră, luați-o de la capăt. Nu există nicio scurtătură `connect_url` pentru pagina găzduită pentru TikTok; deschiderea `oauth_url` pe cont propriu este singura cale.

### Verificarea stării TikTok

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

`openId` este open_id-ul contului TikTok Business, cunoscut odată ce callback-ul OAuth a fost executat.

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

**Răspuns**

```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 nu are o verificare de sănătate live ieftină, așa că `live` este întotdeauna `false` aici - câmpurile reflectă ceea ce a scris conexiunea (sau ultima reîmprospătare a token-ului). `status: "reauth_required"` cu `status_reason` setat înseamnă că contul trebuie să treacă din nou prin procesul de conectare; token-urile TikTok sunt reîmprospătate automat printr-o rotație anuală, iar aceasta este ceea ce apare dacă acea rotație eșuează vreodată.

### Deconectare TikTok

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

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

**Răspuns**

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

---

## GoHighLevel

GoHighLevel (GHL) este o integrare CRM, nu un canal de mesagerie - conectarea acestuia nu consumă un slot de canal din plan, deoarece utilizează canalele existente ale contului în loc să adauge unul nou. Este, de asemenea, singura integrare de pe această pagină care poate menține **mai mult de o conexiune simultan**: fiecare sub-cont GHL ("locație") pe care clientul instalează aplicația primește propria intrare.

### Pasul 1 - Inițierea conexiunii GHL

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

| Câmp | Obligatoriu | Descriere |
|---|---|---|
| `brand` | Nu | Ce listare din marketplace-ul GHL să autorizați. Implicit este listarea standard - relevant doar dacă implementarea dvs. are configurată mai mult de o aplicație de marketplace. |

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

**Răspuns**

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

Deschideți `oauth_url` în browserul titularului de cont pentru ca acesta să poată alege o locație GHL și să aprobe accesul. Starea expiră la `expires_at` (aproximativ 30 de minute).

### Listarea conexiunilor GHL

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

Spre deosebire de alte canale, aceasta nu reprezintă starea unei singure conexiuni - ci listează fiecare locație pe care contul a conectat-o.

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

**Răspuns**

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

### Deconectarea unei locații GHL

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

Șterge conexiunea de aici, ceea ce oprește orice sincronizare și declanșator pentru acea locație. Această acțiune nu dezinstalează aplicația din partea GHL - clientul o elimină din instalările sale din marketplace-ul GHL dacă dorește și acest lucru.

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

**Răspuns**

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

---

## Numere de telefon (cumpărare și eliberare)

În loc să conectați un număr existent, puteți cumpăra direct un număr nou compatibil cu WhatsApp. Căutați numere disponibile, cumpărați unul, apoi interogați până când finalizarea provizionării este completă.

::: note
**Notă:** Numerele cumpărate aici sunt compatibile cu WhatsApp. Înregistrarea expeditorului WhatsApp rulează în fundal după achiziție, așa că trebuie să interogați starea până când ajunge la `ONLINE` înainte de a trimite mesaje. Creditele sunt deduse la achiziție și **nu** sunt rambursate atunci când eliberați numărul.
:::


### Pasul 1 - Căutarea numerelor disponibile

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

| Parametru de interogare | Obligatoriu | Descriere |
|---|---|---|
| `country_code` | Da | Codul de țară ISO 3166-1 alpha-2 în care se face căutarea (de ex. `US`, `GB`, `NL`). |
| `type` | Nu | Clasa de număr preferată, `local` sau `mobile`. Ambele clase pot fi returnate în continuare. |

**Răspuns**

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

Fiecare rezultat afișează `purchase_credits` unic și `monthly_credits` recurent. Un număr furnizat de platformă costă cel puțin 50 de credite pe lună, crescând odată cu prețul lunar al operatorului, taxat la achiziție și la fiecare reînnoire. Citați `purchase_credits` / `monthly_credits` pe care îl returnează căutarea; nu derivați niciodată un preț pe cont propriu. Prima căutare pe un cont nou provisionează unele resurse subiacente, deci poate fi puțin mai lentă decât căutările ulterioare.

### Pasul 2 - Cumpărați un număr

```
POST /phone-numbers
```

Utilizați un `phone_number` din rezultatele căutării.

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

| Câmp | Obligatoriu | Descriere |
|---|---|---|
| `phone_number` | Da | Un număr returnat de căutarea numerelor disponibile, în format E.164. |
| `country_code` | Da | Codul de țară ISO 3166-1 alpha-2 (de exemplu, `US`). |
| `display_name` | Nu | O etichetă prietenoasă. Implicit este numărul de telefon. |
| `category` | Nu | Etichetă opțională de categorie. |

**Răspuns**

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

Numărul începe în starea `PURCHASED`. Înregistrarea WhatsApp continuă apoi în fundal: `PURCHASED` -> `PENDING` -> `ONLINE`.

> Dacă achiziția eșuează deoarece lipsește o adresă de afaceri sau un alt detaliu obligatoriu nu este setat, veți primi un `400` cu un `error` descriptiv. Configurați detaliul lipsă și încercați din nou.

### Pasul 3 - Interogați până la starea ONLINE

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

Acesta este punctul final partajat pentru starea numărului de telefon - funcționează atât pentru numerele WhatsApp cumpărate, cât și pentru celelalte numere conectate.

**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".
```

**Răspuns**

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

### Pasul 4 - Eliberați un număr

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

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

**Răspuns**

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

Ce face acest lucru depinde de cui aparține numărul.

Pentru un număr **închiriat prin intermediul platformei**, este o eliberare propriu-zisă: expeditorul WhatsApp este dezînregistrat, numărul este returnat operatorului și eliminat din cont, se aplică o perioadă de răcire de 7 zile în care numărul nu poate fi răscumpărat de nimeni și nu se rambursează credite.

Pentru un număr **pe care contul l-a adus singur** (propriul cont Twilio, propria aplicație Meta sau cont WhatsApp Business, sau un gateway SMS Android), același apel doar îl elimină din cont. Nimic nu este eliberat la furnizorul din amonte și nu este scris niciun timp de răcire, așa că numărul poate fi reconectat imediat. Înregistrarea expeditorului său WhatsApp, dacă a avut una, poate supraviețui sau nu: procesul de eliminare încearcă să șteargă expeditorul folosind credențialele Twilio gestionate de platformă ale contului. Pe un cont care este încă pe configurația gestionată, acele credențiale sunt valide și expeditorul este șters, deci reconectarea înseamnă înregistrarea lui din nou. Pe un cont care a trecut la propriul Twilio, ștergerea nu se poate autentifica, iar expeditorul rămâne înregistrat în acel cont — reconectarea este atunci doar reatașarea expeditorului existent.

### Adăugarea unui număr pe care îl dețineți deja (BYO)

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

Omite complet fluxul de căutare și cumpărare de mai sus. Utilizați acest lucru atunci când contul își aduce propriul număr (propriul Twilio, propriul cont Meta WhatsApp Business sau un gateway SMS Android) în loc să închirieze unul prin intermediul platformei. Aceasta doar înregistrează numărul - nu se percep credite și nu se provisionează nimic la un furnizor aici. Numărul rămâne inactiv până când titularul contului finalizează OAuth pentru WhatsApp pentru a înregistra un Expeditor pe acesta (același flux pe care îl pornește butonul „Aduceți propriul număr” din tablou de bord).

| Câmp | Obligatoriu | Descriere |
|---|---|---|
| `phone_number` | Da | Numărul de adăugat, în format E.164 (de exemplu, `+14155551234`). |
| `country_code` | Da | Codul de țară ISO 3166-1 alpha-2 (de exemplu, `US`). |
| `display_name` | Nu | O etichetă prietenoasă. Implicit este numărul de telefon. |
| `category` | Nu | Etichetă de categorie opțională. |

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

**Răspuns** (`201 Created`):

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

Un `phone_number` care nu este un număr E.164 real (sau care arată ca numărul de test WhatsApp al Meta, care nu poate trimite niciodată mesaje clienților reali) returnează `400`. Adăugarea unui număr care există deja în cont - chiar dacă este scris ușor diferit, cum ar fi formele `+52` vs `+521` din Mexic - returnează `409` în loc să creeze un rând duplicat.

### Setarea unui număr ca principal

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

Comută un număr la `is_active: true` și toate celelalte numere din cont la `is_active: false`, atomic - contul nu ajunge niciodată să aibă două numere active sau niciunul în timpul solicitării. `is_active` nu poate fi setat prin endpoint-ul general de actualizare în mod intenționat; acest apel dedicat este singura modalitate de a schimba numărul principal.

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

**Răspuns**

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

`phone_number` de aici este obiectul complet al numărului (aceeași formă pe care o returnează `GET /phone-numbers`), nu doar șirul. Un `phoneNumber` care nu se află în cont returnează `404`.

### Eliminarea înregistrării unui număr (fără a-l elibera)

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

O ștergere simplă a înregistrării numărului din acest cont - fără eliberare sau dezînregistrare din partea furnizorului și fără perioada de răcire de 7 zile care se aplică pasului de eliberare de mai sus. Utilizați acest lucru pentru a șterge înregistrările BYO, WhatsApp Web, Telegram sau LINE, sau o intrare învechită, fără a trece prin fluxul de eliberare gestionat. Spre deosebire de o eliberare, ștergerea unui număr care nu se află în cont este un `404`, nu un succes silențios.

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

**Răspuns**

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

---

## Direcționați un canal către o campanie

Conectarea unui canal aduce mesajele **în** cont. Aceasta nu decide **ce Agent AI le răspunde**.

Rutarea este gestionată de **Puncte de Intrare** (Entry Points) pe un Agent AI, nu de campanii. Fiecare canal are un Punct de Intrare implicit care numește Agentul ce răspunde contactelor noi, necunoscute, pe acel canal:

| Ce doriți să faceți | Apel |
|---|---|
| Direcționați un canal către Agentul care ar trebui să răspundă | `PUT /entry-points/channel-defaults` cu corpul `{ "channel": "instagram", "agent_id": "AGENT_ID" }` |
| Verificați dacă ierarhia Punctelor de Intrare este activă pentru cont | `GET /entry-points/routing-status`, care returnează `{ "success": true, "cutover_enabled": true }` odată ce Punctele de Intrare decid rutarea acelui cont |
| Lăsați un canal fără niciun Agent care să răspundă | `DELETE /entry-points/channel-defaults?channel=instagram` |

Până când un canal are un Punct de Intrare (Entry Point), un prim mesaj de la cineva cu care nu ați mai vorbit este stocat, dar nimic nu îl preia și niciun asistent nu răspunde. Acesta este pasul pe care majoritatea integrărilor îl omit: conectarea Instagram și crearea unui Agent nu sunt suficiente de la sine — trebuie, de asemenea, să direcționați canalul către Agent. Setul complet de apeluri — incluzând un Agent per număr de WhatsApp, cuvinte cheie și reguli pentru comentarii — se află în [API-ul Punctelor de Intrare](entry-points.md).

`POST /channels/campaign` scrie în continuare harta de rutare a campaniilor per-canal moștenită, documentată mai jos, dar acea hartă nu mai este consultată pentru rutarea de intrare pe niciun cont; este păstrată doar pentru rollback. Nu construiți pe baza ei.

### Rutarea unuia sau mai multor canale (hartă de rutare a campaniilor moștenită)

`POST /channels/campaign`

**Câmpuri de solicitare**

| Câmp | Obligatoriu | Descriere |
|---|---|---|
| `campaign_id` | Da | Campania care ar trebui să răspundă contactelor noi de pe aceste canale. Trebuie să aparțină contului. |
| `channels` | Da | O matrice nevidă de canale de direcționat. Permise: `whatsapp`, `whatsapp_web`, `telegram`, `instagram`, `messenger`, `chat_widget`, `custom_channel`, `sms`, `email`. |

Slotul de direcționare și lista `enabled_channels` a campaniei sunt actualizate împreună într-o singură operațiune atomică, astfel încât să nu poată fi niciodată nealiniate. Un canal deja direcționat către o altă campanie este pur și simplu redirecționat către aceasta.

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

**Răspuns**

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

### Ce trebuie să fie adevărat pentru ca direcționarea să funcționeze efectiv

Pe un cont care încă citește harta de rutare a campaniilor moștenită, rutarea reușește ca apel API, dar trei lucruri din campanie decid dacă un mesaj real de intrare primește răspuns. Verificați toate cele trei aspecte atunci când un canal rutat rămâne tăcut.

| Cerință | Ce se întâmplă în caz contrar |
|---|---|
| `type` este `Incoming from Unknown Contacts` sau `Combined` | Cererea este respinsă cu `400`. Campaniile de ieșire și cele bazate pe cuvinte cheie nu pot deține un slot de rutare. |
| `status` este `Live` | Rutarea este stocată, dar nu preia nimic. O campanie `Draft` este cea mai frecventă cauză pentru „Am rutat-o și nu se întâmplă nimic”. |
| `ai_mode` este `true` | Contactul este creat și mesajul stocat, dar asistentul nu răspunde niciodată. |

Potrivirea cuvintelor cheie se află acum în Punctele de Intrare — creați un Punct de Intrare de tip `keyword` pe Agentul AI care ar trebui să răspundă.

### O campanie per canal

Fiecare canal deține exact un slot de rutare moștenit. Rutarea unei a doua campanii către același canal redirecționează silențios slotul și returnează `200` — nu există nicio eroare de conflict. Campania anterioară continuă să gestioneze contactele pe care le are deja; pur și simplu nu mai primește altele noi.

### Șterge rutarea unui canal

`DELETE /channels/campaign/{channel}`

Elimină rutarea pentru un singur canal, indiferent de campania către care indică în prezent, și elimină canalul din `enabled_channels` acelei campanii. Contactele noi necunoscute de pe canal nu mai sunt preluate de nicio campanie. Contactele deja aflate în campanie își continuă activitatea ca înainte.

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

**Răspuns**

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

Este idempotentă: ștergerea unui canal care nu a fost niciodată rutat returnează de asemenea `200`, cu `cleared: false` și `campaign_id: null`. Acest endpoint necesită funcționalitatea **campanii primite** în planul tău; fără aceasta, vei primi un `403`.


---

## Utilizați propria aplicație Meta (Instagram + Messenger)

În mod implicit, conexiunea Instagram + Messenger rulează prin aplicația Meta a platformei, astfel încât numele acelei aplicații este ceea ce vede titularul contului pe ecranul de consimțământ Facebook. Dacă doriți ca ecranul de consimțământ să afișeze **brandul dvs.**, puteți să vă înregistrați propria aplicație Meta și să direcționați întregul flux prin aceasta. Odată configurată, aceasta se aplică contului dvs. — nimic nu se schimbă în apelurile de conectare de mai sus, cu excepția brandingului.

> **Acest lucru acoperă doar Instagram + Messenger.** Conexiunile WhatsApp, WhatsApp Web, Telegram și LINE nu sunt afectate de o aplicație Meta personalizată.

### De ce are nevoie aplicația dumneavoastră mai întâi

Aceasta este partea care necesită timp și se întâmplă în întregime pe partea Meta:

1. **O aplicație** de tip Business, cu produsele Messenger și Instagram adăugate.
2. **Acces avansat** (prin Meta App Review) pentru: `pages_show_list`, `pages_messaging`, `pages_manage_metadata`, `pages_read_engagement`, `instagram_basic`, `instagram_manage_messages`. Fără acces avansat, doar persoanele care dețin un rol în aplicația dumneavoastră pot finaliza conexiunea — conexiunile clienților dumneavoastră vor eșua. Revizuirea aplicației durează de obicei câteva săptămâni și necesită verificarea afacerii (Business Verification).
3. **O configurație Facebook Login for Business** creată în interiorul aplicației dumneavoastră, care acordă aceleași permisiuni. ID-ul său numeric de configurare este per aplicație, deci trebuie să îl creați pe al dumneavoastră.

Dacă aplicației dumneavoastră îi lipsește oricare dintre permisiunile necesare, conexiunea eșuează în momentul conectării cu o eroare clară care indică ce lipsește (vizibilă în sondajul `/status` ca `byo_app_missing_permissions`) — în loc să pară că funcționează și să eșueze la primul mesaj.

### Pasul 1 - Salvați aplicația

`PUT /account-config/meta-app`

| Câmp | Obligatoriu | Descriere |
|---|---|---|
| `app_id` | Da | ID-ul aplicației Meta (Setări → De bază). |
| `app_secret` | Da | Secretul aplicației Meta. Verificat în raport cu Meta înainte de a fi stocat, apoi criptat. Nu este returnat niciodată de niciun punct final. |
| `config_id` | Da | ID-ul numeric al configurației Facebook Login for Business din interiorul aplicației dumneavoastră. |

Toate cele trei sunt necesare pentru fluxul de Autentificare Facebook. Dacă rulați doar calea de trimitere a tokenului pentru Autentificarea Instagram descrisă mai jos, le puteți omite complet.

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

**Răspuns**

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

### Pasul 2 - Configurați aplicația pentru a comunica cu noi

În tabloul de bord al aplicației Meta:

1. **Webhooks** - atât pentru produsele Instagram, cât și pentru Messenger, setați URL-ul de callback la valoarea `webhook_urls` corespunzătoare din răspuns și tokenul de verificare la `verify_token`. Abonați-vă la câmpurile `messages`, `messaging_postbacks` și `comments`.
2. **URI-uri de redirecționare OAuth valide** - adăugați `https://api.youraiconnector.com/v1/auth-meta-callback-handler` pentru ca fluxul de consimțământ să poată reveni.

`GET /account-config/meta-app` returnează același material de configurare oricând; `DELETE /account-config/meta-app` elimină aplicația (conexiunile viitoare revin la aplicația platformei — eliminați, de asemenea, abonamentul webhook din interiorul aplicației dumneavoastră).

### Pasul 3 - Conectați-vă ca de obicei

Nimic altceva nu se schimbă. `POST /channels/meta/connect` (și pagina găzduită `connect_url`) utilizează automat aplicația dvs. pentru contul dvs.; `uses_byo_meta_app: true` din răspuns confirmă ce aplicație va afișa ecranul de consimțământ. Trimiterea mesajelor, selectarea paginii și deconectările funcționează identic.

## Aduceți propria aplicație de autentificare Instagram (push de token)

Secțiunea de mai sus acoperă fluxul de autentificare Facebook, unde contul se conectează printr-o pagină de Facebook. Meta oferă, de asemenea, **API-ul Instagram cu autentificare Instagram** (Business Login for Instagram): deținătorul contului se autentifică direct pe Instagram, fără a fi nevoie de un cont sau o pagină de Facebook.

Dacă platforma dvs. rulează deja propria aplicație Meta cu acel produs, nu aveți nevoie deloc de niciun flux OAuth din partea noastră. Clienții dvs. autorizează **aplicația dvs.**, iar dvs. ne trimiteți (push) acreditările finalizate pentru fiecare cont:

1. Salvați acreditările aplicației dvs. Instagram o singură dată (pentru a putea verifica webhook-urile dvs.).
2. Pentru fiecare cont, trimiteți ID-ul contului profesional de Instagram + tokenul de utilizator Instagram pe termen lung obținut de aplicația dvs.
3. Direcționați webhook-ul de mesagerie Instagram al aplicației dvs. către noi. Evenimentele pentru conturile pe care nu le-ați trimis sunt confirmate și ignorate.
4. Dvs. dețineți ciclul de viață al tokenului: reîmprospătați tokenurile în propriul sistem și trimiteți fiecare token reîmprospătat cu același apel. Noi nu reîmprospătăm niciodată un token trimis prin push.

### De ce are nevoie aplicația dumneavoastră mai întâi

- Produsul **Instagram** („API setup with Instagram login”) adăugat la aplicația dvs. Meta. Acest produs are propria **pereche de App ID și App Secret**, separată de App ID/Secret-ul de Facebook — le găsiți în panoul de configurare al produsului.
- **Acces avansat** (prin Meta App Review) pentru `instagram_business_basic` și `instagram_business_manage_messages` (adăugați `instagram_business_manage_comments` dacă utilizați automatizări pentru comentarii). Fără acesta, doar persoanele cu un rol în aplicația dvs. o pot autoriza.

### Pasul 1 - Salvați acreditările aplicației dvs. Instagram

Același endpoint ca mai sus — trimiteți perechea Instagram către `PUT /account-config/meta-app`. Câmpurile Facebook nu sunt necesare pentru această cale: trimiteți perechea singură dacă rulați doar Autentificarea Instagram, sau împreună cu câmpurile Facebook dacă le rulați pe amândouă. O salvare descrie întotdeauna întreaga setare, deci orice set omiteți va fi eliminat.

| Câmp | Obligatoriu | Descriere |
|---|---|---|
| `instagram_app_id` | Împreună | ID-ul numeric de aplicație al produsului Instagram (nu ID-ul de aplicație Facebook). |
| `instagram_app_secret` | Împreună | Cheia secretă (App Secret) a produsului Instagram. Criptată în repaus, nu este returnată niciodată. |

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

**Răspuns** — conține URL-ul webhook-ului pentru Autentificarea Instagram (URL-urile `instagram` și `messenger` apar doar atunci când sunt stocate și câmpurile Facebook):

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

În panoul **Webhooks** al aplicației dvs. pentru produsul Instagram, setați Callback URL la `webhook_urls.instagram_login`, Verify token la `verify_token` și abonați-vă la câmpurile `messages` și `comments`.

### Pasul 2 - Trimiteți (push) un token per cont

`PUT /channels/instagram-login/token`

Funcționează cu `sub_account_id` ca orice altă rută, astfel încât o cheie de agenție poate furniza întreaga sa flotă.

| Câmp | Obligatoriu | Descriere |
|---|---|---|
| `ig_user_id` | Da | **ID-ul contului profesional de Instagram** — câmpul `user_id` din `GET https://graph.instagram.com/v21.0/me?fields=user_id,username`. Acesta este același ID pe care webhook-urile Instagram îl transmit ca `entry.id`. ⚠️ **Nu** este câmpul `id` din `/me` — acela este limitat la aplicație și diferă în funcție de aplicația Meta. Trimiterea ID-ului limitat la aplicație returnează o eroare `400` care indică greșeala. |
| `access_token` | Da | Tokenul de utilizator Instagram pe termen lung pe care aplicația dvs. l-a obținut pentru acel cont. Validat în timp real pe Instagram înainte de a fi stocat: tokenul trebuie să fie funcțional și să aparțină `ig_user_id`. |
| `expires_at` | Nu | Data expirării tokenului în format ISO-8601. Alternativ, trimiteți `expires_in` (secunde). Valoarea implicită este de 60 de zile. |
| `username` | Nu | @handle-ul contului; oricum îl citim de pe Instagram. |

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

**Răspuns**

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

Ca parte a procesului de push, abonăm aplicația dvs. la webhook-urile acelui cont (`subscribed_apps` cu tokenul trimis), astfel încât mesajele să înceapă să curgă fără niciun apel suplimentar din partea dvs.

**Reîmprospătare** - trimiteți jetonul reîmprospătat către același punct final cu același `ig_user_id`; acesta actualizează jetonul stocat și data expirării pe loc.

**Conflicte** - un cont de Instagram nu este niciodată activ pe două conexiuni. Dacă respectivul cont este deja conectat în altă parte sau prin acest cont prin fluxul Paginii de Facebook, cererea returnează un `409` care vă indică ce conexiune să deconectați mai întâi. O conexiune prin fluxul Facebook nu este niciodată înlocuită automat, deoarece poate deservi și Messenger.

### Pasul 3 - Deconectați când un client pleacă

`DELETE /channels/instagram-login/token` (aceeași autentificare și `sub_account_id`) dezabonează webhook-urile prin „best-effort” și elimină acreditarea stocată. Aceasta reușește întotdeauna, chiar și atunci când jetonul a expirat deja — iar odată ce acreditarea a fost eliminată, evenimentele webhook ale acelui cont sunt ignorate.

---

## Sfaturi pentru construirea unui wrapper fiabil

- **Interogați cu moderație.** La fiecare câteva secunde este suficient. Opriți-vă odată ce ajungeți la o stare terminală (`connected` / `ONLINE` sau o stare de eșec) și setați un timeout general rezonabil pentru buclă (pașii browser/QR expiră, consultați fiecare `expires_at`).
- **Codificați URL-ul numerelor de telefon în cale.** Simbolul `+` de la început ar trebui trimis ca `%2B`. Endpoint-urile recuperează și cifrele brute, dar codificarea este varianta implicită sigură.
- **Nu vă așteptați niciodată să primiți secrete înapoi.** Token-urile de acces, secretele canalului și token-urile de pagină sunt acceptate sau stocate, dar nu sunt niciodată returnate în niciun răspuns.
- **Gestionați poarta de autentificare.** Un `403` înseamnă că accesul API nu este inclus în plan sau că canalul pe care îl conectați nu este inclus în planul contului. Consultați [Acces API](../integrations/api-access.md).
- **Atenție la limita de rată.** Cererile autentificate sunt limitate la 300 pe minut; un `429` înseamnă să faceți o pauză și să reîncercați. Consultați [Autentificare](authentication.md).

## Pașii următori

- [Autentificare](authentication.md) - cele patru forme de autentificare acceptate și formatul erorilor.
- [Acces API](../integrations/api-access.md) - generarea și gestionarea cheii API.
