
# API Koneksi Saluran

Panduan ini menunjukkan cara menghubungkan saluran pesan ke akun menggunakan API. Panduan ini ditulis untuk pengembang yang membangun integrasi atau wrapper, sehingga fokus pada permintaan yang tepat, urutan pembuatannya, dan respons yang Anda terima.

Ada satu pola yang perlu Anda pahami sejak awal, karena pola ini berlaku untuk hampir setiap saluran di sini.

## Pola hubungkan-lalu-polling

Sebagian besar saluran tidak dapat dihubungkan dengan satu panggilan API saja. Menghubungkan WhatsApp, Instagram, atau Messenger berarti pemilik akun harus masuk ke akun penyedia mereka sendiri dan menyetujui akses. **Tidak ada jalur headless (otomatis sepenuhnya)** untuk persetujuan tersebut - orang sungguhan harus membuka URL di browser, atau memindai kode QR dengan ponsel mereka.

Jadi alurnya selalu:

1. **Mulai koneksi** dengan `POST`. Respons memberikan Anda URL untuk dibuka, atau kode QR untuk ditampilkan.
2. **Serahkan itu kepada pengguna akhir** - buka URL di browser mereka, atau tampilkan kode QR di layar untuk mereka pindai.
3. **Polling endpoint status** dengan `GET` dalam interval singkat (setiap beberapa detik) hingga status mencapai status terhubung.

Tugas integrasi Anda adalah menjalankan loop tersebut: tampilkan URL atau QR, lalu polling hingga selesai. Rencanakan UI Anda di sekitar polling - spinner dengan pesan "menunggu Anda selesai di browser" berfungsi dengan baik.

::: note
**Catatan:** Sebelum memulai, pastikan akses API telah diaktifkan pada paket Anda dan Anda memiliki kunci API. Lihat [Akses API](../integrations/api-access.md) untuk mengetahui cara membuatnya. Semua permintaan di bawah menggunakan URL dasar `https://api.youraiconnector.com/v1` dan Anda harus mengautentikasi setiap permintaan. Lihat [Autentikasi](authentication.md) untuk empat bentuk yang diterima - contoh di sini menggunakan header `X-API-Key`, dengan satu contoh cURL per halaman yang menunjukkan bentuk kueri `?apiKey=` yang lebih sederhana.
:::


---

## Instagram + Messenger (Meta)

Instagram dan Messenger dihubungkan bersama dalam satu alur, karena keduanya berjalan di Halaman Facebook. Pemilik akun memberikan otorisasi melalui Facebook, Anda mengambil daftar Halaman yang mereka kelola, dan Anda memilih Halaman mana yang akan dihubungkan.

### Langkah 1 - Memulai koneksi Instagram + Messenger

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

Ini mengembalikan URL persetujuan. Tidak ada kredensial yang dikirim dalam permintaan ini - koneksi diotorisasi sepenuhnya di 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.
```

**Respons**

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

Buka `oauth_url` di browser pengguna akhir agar mereka dapat masuk ke Facebook dan menyetujui akses. Upaya koneksi kedaluwarsa pada `expires_at` (sekitar 30 menit) - jika sudah lewat, mulai dari awal. Perlakukan `state_token` sebagai rahasia berumur pendek dan jangan mencatatnya.

### Opsi termudah untuk Instagram + Messenger: serahkan `connect_url`

Respons tersebut juga menyertakan `connect_url` siap pakai: halaman yang dihosting yang menjalankan seluruh alur untuk pemegang akun. Mereka membukanya, masuk ke Facebook, dan jika mereka memiliki lebih dari satu Halaman, halaman tersebut akan menampilkan daftar dan membiarkan mereka memilih Halaman mana yang akan dihubungkan - kemudian halaman tersebut melaporkan keberhasilan dengan sendirinya. Berikan tautan ini kepada pemegang akun alih-alih membuka `oauth_url` sendiri, membuat pemilih Halaman, dan melakukan polling. Tautan ini berfungsi selama sekitar 30 menit (`connect_url_expires_at`); jika kedaluwarsa, mulai koneksi baru. Langkah-langkah manual di bawah ini ditujukan untuk integrasi yang ingin menjalankan alur dan merender pemilih Halaman sendiri.

### Langkah 2 - Lakukan polling status hingga halaman dimuat

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

Setelah pengguna menyelesaikan login Facebook, lakukan polling pada endpoint ini setiap beberapa detik. Bidang `status` akan melalui langkah-langkah berikut:

| `status` | Arti |
|---|---|
| `pending` | Persetujuan belum selesai. Terus tunggu. |
| `token_received` | Diotorisasi, tetapi daftar Halaman masih dimuat. |
| `pages_loaded` | Halaman tersedia - lanjutkan ke langkah 3. |
| `connected` | Halaman telah dipilih dan saluran sudah aktif. |

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

**Respons (setelah halaman dimuat)**

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

### Langkah 3 - Mencantumkan halaman (opsional)

Jika Anda lebih suka mengambil daftar Halaman secara terpisah (misalnya, untuk merender pemilih), gunakan:

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

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

Ini mengembalikan array `pages` yang sama seperti endpoint status. (Endpoint `status` sudah menyertakan halaman, jadi panggilan ini hanya untuk kenyamanan.)

### Langkah 4 - Pilih halaman untuk dihubungkan

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

Kirim `page_id` dari Halaman yang dipilih pengguna. Akun Instagram yang ditautkan ke Halaman tersebut akan dihubungkan secara otomatis; Anda hanya memerlukan objek `instagram` jika ingin mengganti akun Instagram mana yang akan digunakan.

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

**Respons**

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

Saluran sekarang terhubung. `GET /channels/meta/status` tindak lanjut akan melaporkan `status: "connected"`.

### Mencantumkan kiriman halaman yang terhubung

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

Mengembalikan kiriman terbaru dari halaman yang Anda hubungkan - media Instagram atau kiriman Facebook. Inilah yang Anda gunakan untuk merender pemilih saat Anda menyiapkan Titik Masuk yang bereaksi terhadap komentar pada satu kiriman tertentu.

| Parameter kueri | Wajib | Deskripsi |
|---|---|---|
| `platform` | Ya | `instagram` atau `facebook`. Selain itu akan mengembalikan `400`. |
| `limit` | Tidak | Berapa banyak kiriman yang akan dikembalikan, `1`-`50`. Defaultnya adalah `25`. |
| `after` | Tidak | Kursor untuk halaman berikutnya - teruskan nilai `nextCursor` dari respons sebelumnya. |

**cURL**

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

**Respons**

```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` adalah label milik Instagram (`REELS`, `FEED`, `STORY`, atau formatnya - `IMAGE`, `VIDEO`, `CAROUSEL_ALBUM`); untuk Facebook selalu `POST`. `nextCursor` adalah `null` pada halaman terakhir.

Jika tidak ada yang dapat dicantumkan, panggilan tetap mengembalikan `200` dengan `connected: false` dan array `posts` kosong, ditambah `reason` yang memberi tahu Anda alasannya:

| `reason` | Apa yang harus dilakukan |
|---|---|
| _(tidak ada)_ | Belum ada halaman yang terhubung - jalankan alur hubungkan terlebih dahulu. |
| `no_instagram_account` | Halaman Facebook terhubung tetapi tidak ada akun bisnis Instagram yang ditautkan ke halaman tersebut. Kiriman Facebook tetap dapat dicantumkan dengan baik. |
| `token_expired` | Kredensial halaman yang disimpan tidak lagi berfungsi - hubungkan kembali saluran tersebut. |

### Memutuskan koneksi Instagram + Messenger

```
DELETE /channels/meta
```

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

**Respons**

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

Ini menghentikan perutean masuk untuk Instagram dan Messenger. Ini bersifat idempoten - memanggilnya saat tidak ada yang terhubung akan tetap berhasil.

---

## WhatsApp Business

Ini menghubungkan nomor WhatsApp Business resmi. Nomor tersebut harus sudah ada di akun sebelum Anda memanggil connect. Seperti Meta, pemegang akun melakukan otorisasi di browser mereka, kemudian Anda melakukan polling hingga nomor tersebut melaporkan `ONLINE`.

### Langkah 1 - Memulai koneksi 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.
```

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `phone_number` | Ya | Nomor yang akan dihubungkan, dalam format E.164 (contoh: `+14155551234`). |
| `only_waba_sharing` | Tidak | Membatasi otorisasi untuk berbagi Akun WhatsApp Business yang sudah ada, melewati pengaturan pengirim baru. Default-nya adalah `false`. |
| `retry` | Tidak | Menjalankan ulang otorisasi untuk nomor yang upaya sebelumnya tidak selesai. Default-nya adalah `false`. |
| `business_name` | Tidak | Penggantian kosmetik untuk nama bisnis yang ditampilkan di layar persetujuan saja (maks 256 karakter). Tidak disimpan. |
| `description` | Tidak | Penggantian kosmetik untuk deskripsi bisnis yang ditampilkan di layar persetujuan saja (maks 256 karakter). Tidak disimpan. |

**Respons**

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

Buka `oauth_url` di browser pemegang akun untuk melakukan otorisasi. Setelah mereka menyetujui, pendaftaran selesai di latar belakang.

### Langkah 2 - Lakukan polling status hingga ONLINE

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

Lakukan polling ini hingga `status` bernilai `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".
```

**Respons**

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

Bidang `status` dapat berupa:

| `status` | Arti |
|---|---|
| `PENDING` | Diotorisasi, persetujuan masih berlangsung. Terus lakukan polling. |
| `ONLINE` | Terhubung dan siap mengirim. |
| `RATE_LIMITED` | Terlalu banyak percobaan - tunggu sebelum mencoba lagi. |
| `REGISTRATION_FAILED` | Pengaturan tidak dapat diselesaikan. |
| `DELETED` | Pendaftaran tidak lagi ada. |

`live: true` berarti status diperiksa terhadap penyedia secara real time; `false` berarti status berasal dari status cache terakhir.

### Memutuskan koneksi nomor 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"
```

**Respons**

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

Nomor itu sendiri tetap ada di akun, sehingga Anda dapat menghubungkannya kembali nanti.

---

## WhatsApp Web

WhatsApp Web menautkan nomor WhatsApp biasa dengan memindai kode QR, sama seperti menautkan perangkat di aplikasi WhatsApp. Alurnya adalah: mulai sesi, ambil kode QR dan tampilkan, lalu lakukan polling hingga statusnya menjadi `connected`.

### Langkah 1 - Memulai sesi penyandingan 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()
```

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `phone_number` | Ya | Nomor WhatsApp yang akan dihubungkan, dalam format E.164. |
| `proxy_country` | Tidak | Kode negara ISO 3166-1 alpha-2 untuk wilayah perutean. Dideteksi otomatis dari nomor jika dihilangkan. |
| `force_new` | Tidak | Buang sesi yang ada dan mulai pemasangan baru. Default-nya adalah `false`. |
| `import_contacts` | Tidak | Impor kontak perangkat yang ada pada koneksi pertama. Default-nya adalah `false`. |
| `pause_ai_for_imported_contacts` | Tidak | Saat mengimpor kontak, tetap jeda balasan otomatis untuk mereka. Default-nya adalah `true`. |
| `import_existing_chats` | Tidak | Impor riwayat obrolan yang ada (memerlukan `import_contacts: true`). Default-nya adalah `false`. |

**Respons**

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

### Opsi termudah untuk WhatsApp Web: serahkan `connect_url`

Respons tersebut mencakup `connect_url` siap pakai: halaman yang dihosting yang menampilkan kode QR, menyegarkannya secara otomatis saat berotasi, dan beralih ke pesan sukses saat nomor tersebut ditautkan. Cukup berikan tautan ini kepada pemegang akun (buka di browser, kirimkan kepada mereka, atau tampilkan sebagai QR/tombol) dan minta mereka memindainya dengan WhatsApp - Anda tidak perlu mengambil QR atau melakukan polling apa pun sendiri. Tautan ini berfungsi selama sekitar 30 menit (`connect_url_expires_at`); jika kedaluwarsa sebelum mereka selesai, mulai koneksi baru untuk mendapatkan yang baru.

Ini adalah jalur yang disarankan jika seseorang dapat membuka tautan. Langkah-langkah manual di bawah ini (mengambil QR sendiri, melakukan polling status) ditujukan untuk integrasi yang ingin merender QR di dalam antarmuka mereka sendiri.

Respons tersebut juga memberikan Anda `poll_qr_path` dan `poll_status_path` yang tepat untuk digunakan, sehingga Anda tidak perlu membuatnya sendiri.

### Langkah 2 - Mengambil kode QR dan menampilkannya

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

**Respons**

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

Tampilkan QR agar pengguna dapat memindainya dengan ponsel mereka (WhatsApp > Perangkat Tertaut > Tautkan Perangkat):

- `qr_data_url` adalah gambar yang siap digunakan - masukkan langsung ke dalam `<img src>`.
- `qr_code` adalah payload mentah jika Anda lebih suka membuat gambarnya sendiri.

QR tersebut berumur pendek. Jika Anda memanggil ini tepat setelah memulai sesi, Anda mungkin mendapatkan `404` dengan pesan "QR code not available yet" - tunggu sebentar dan coba lagi. Jika Anda mendapatkan `410` ("QR code expired"), mulai ulang koneksi untuk mendapatkan kode baru.

### Langkah 3 - Melakukan polling status hingga terhubung

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

**Respons**

```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` | Arti |
|---|---|
| `not_initialized` | Belum ada sesi (kegagalan terminal). |
| `qr_pending` | Menunggu QR dipindai. |
| `connecting` | Dipindai, menyelesaikan penyiapan. |
| `connected` / `open` | Tertaut dan aktif - ini adalah keberhasilan. |
| `disconnected` | Sesi berakhir (kegagalan terminal). |

### Memutuskan sesi 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"
```

**Respons**

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

Ini akan memutuskan tautan perangkat dan menghapus koneksi. Tindakan ini selalu membersihkan status lokal, sehingga bersifat idempoten meskipun sesi yang mendasarinya sudah tidak ada.

---

## Telegram

> **Ketersediaan:** Telegram terhubung seperti saluran lainnya dan terbuka untuk setiap akun — Anda tidak perlu mengaktifkannya secara khusus. Endpoint Telegram di bawah ini masih dapat mengembalikan `403` jika Telegram tidak termasuk dalam paket akun, yang dalam kasus tersebut pesan kesalahannya berbunyi `"This channel is not included in your current plan. Upgrade to unlock it."`.

Telegram menghubungkan akun pribadi melalui nomor telepon ditambah kode login sekali pakai (dan kata sandi dua faktor, jika akun telah mengaturnya). Alurnya adalah: mulai sesi, kirim kode, kirim kata sandi secara opsional, lalu konfirmasi melalui status.

### Langkah 1 - Memulai sesi koneksi 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()
```

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `phone_number` | Ya | Nomor telepon akun yang akan dihubungkan, dalam format E.164. |
| `mode` | Tidak | `code` (default) mengirimkan kode login sekali pakai ke akun; `qr` mengembalikan token login dan URL QR untuk ditampilkan. |
| `proxy_country` | Tidak | Kode negara ISO 3166-1 alpha-2 untuk rute jaringan keluar. |
| `force_new` | Tidak | Jika `true`, membuang sesi yang ada dan memulai dari awal. |

**Respons**

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

Dalam mode `code`, akun menerima kode login di Telegram dan `status` adalah `code_required`. (Dalam mode `qr`, respons juga menyertakan `login_token` dan `qr_url` untuk ditampilkan agar dipindai, dan `status` adalah `qr_required`.)

### Opsi termudah untuk Telegram: serahkan `connect_url`

Respons tersebut menyertakan `connect_url` yang siap pakai: halaman yang dihosting yang menyelesaikan koneksi dengan sendirinya. Dalam mode `code`, pemilik akun memasukkan kode login - dan kata sandi verifikasi dua langkah jika akun mereka memilikinya. Dalam mode `qr`, halaman tersebut menampilkan kode QR yang diperbarui secara otomatis untuk dipindai oleh mereka dari aplikasi Telegram. Bagaimanapun, halaman ini melaporkan keberhasilan secara mandiri, jadi Anda cukup memberikan tautan ini kepada pemilik akun alih-alih membangun UI Anda sendiri dan melakukan polling. Tautan ini berfungsi selama sekitar 30 menit (`connect_url_expires_at`); jika kedaluwarsa, mulai koneksi baru untuk mendapatkan yang baru.

Langkah-langkah manual di bawah ini (mengumpulkan kode sendiri, mengirimkannya, melakukan polling status; atau merender `qr_url` dan melakukan polling) ditujukan untuk integrasi yang ingin merender UI sendiri.

### Langkah 2 - Mengirimkan kode login

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

**Respons**

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

Jika `status` adalah `connected`, Anda selesai. Jika akun mengaktifkan dua faktor, `status` akan menjadi `password_required` - lanjutkan ke langkah 3.

### Langkah 3 - Mengirimkan kata sandi dua faktor (hanya jika diperlukan)

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

Hanya panggil ini saat langkah 2 mengembalikan `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()
```

**Respons**

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

### Memeriksa status 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"
```

**Respons**

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

`status` bisa berupa `connected`, `code_required`, `password_required`, `initializing`, `disconnected`, `not_initialized`, atau `error`.

### Memutuskan koneksi Telegram

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

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

**Respons**

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

Idempotent - panggilan berulang akan berhasil.

---

## Instagram (akun pribadi)

> Beta dengan ketersediaan terbatas, diaktifkan per akun. Ini menghubungkan akun Instagram pribadi dengan masuk menggunakan nama pengguna dan kata sandinya (bukan API Bisnis resmi). Jika akun tidak diaktifkan untuk beta, panggilan koneksi akan mengembalikan kesalahan izin.

Karena ini memerlukan login Instagram milik pemegang akun itu sendiri, cara termudah adalah dengan memberikan `connect_url` yang dihosting kepada mereka dan membiarkan mereka memasukkan kredensial mereka di sana - integrasi Anda tidak akan pernah menangani kata sandi tersebut.

### Langkah 1 - Memulai koneksi Instagram (pribadi)

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

Kirim Instagram `username` dan `password`.

**Respons**

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

Jika akun memiliki autentikasi dua faktor atau Instagram menampilkan pemeriksaan, `status` akan kembali sebagai `two_factor_required` atau `challenge_required` - kirimkan kode ke `/connect/{id}/verify-2fa` atau `/connect/{id}/verify-challenge` di bawah, lalu polling `/connect/{id}/status` hingga `connected`. `{id}` adalah nama pengguna Instagram yang dinormalisasi yang dikembalikan sebagai `account_id`/`username` dalam respons di atas - gunakan pada setiap langkah di bawah.

### Langkah 2 - Kirimkan kode dua faktor (jika diminta)

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

Hanya panggil ini saat langkah 1 (atau langkah 3) mengembalikan `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" }'
```

**Respons**

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

`status` dapat kembali sebagai `connected` (selesai), `two_factor_required` (kode salah, coba lagi), atau `challenge_required` (Instagram juga meminta kode pemeriksaan - buka langkah 3).

### Langkah 3 - Kirimkan kode konfirmasi pemeriksaan (jika diminta)

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

Hanya panggil ini saat langkah sebelumnya mengembalikan `challenge_required`. Bentuk permintaan dan respons yang sama seperti langkah 2 di atas.

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

### Periksa status Instagram (pribadi)

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

Polling ini hingga `status` adalah `connected`, atau hingga melaporkan kegagalan terminal.

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

**Respons**

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

`status` bisa berupa `connected`, `two_factor_required`, `challenge_required`, `initializing`, `disconnected`, `not_initialized`, atau `error`. `live: true` berarti ini dibaca langsung dari pekerja koneksi alih-alih nilai yang di-cache.

### Opsi termudah untuk Instagram (pribadi): serahkan `connect_url`

Respons tersebut menyertakan `connect_url`: halaman yang dihosting tempat pemegang akun memasukkan nama pengguna dan kata sandi Instagram mereka (serta kode 2FA atau pos pemeriksaan jika Instagram memintanya), dan yang melaporkan keberhasilan dengan sendirinya. Kredensial langsung dikirim ke Instagram dan tidak disimpan. Berikan tautan ini kepada pemegang akun alih-alih mengumpulkan kata sandi mereka di UI Anda sendiri. Tautan ini berfungsi selama sekitar 30 menit (`connect_url_expires_at`).

### Putuskan sambungan Instagram (pribadi)

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

Idempotent - panggilan berulang akan berhasil.

### Sinkronisasi pengikut

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

Memicu sinkronisasi pengikut secara manual untuk akun yang terhubung - pekerjaan yang sama yang berjalan secara otomatis di latar belakang, ditampilkan di sini untuk tindakan "Segarkan pengikut" sesuai permintaan. Ini mengambil daftar pengikut akun saat ini, mencatat siapa pun yang baru, dan (saat kampanye Langsung mengaktifkan penjangkauan pengikut) mengirimkan DM pembuka kepada pengikut baru, hingga batas harian.

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

**Respons**

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

> Kelima kolom ini adalah satu-satunya tempat di halaman ini yang mengembalikan `camelCase` alih-alih `snake_case` - begitulah cara endpoint ini diatur saat ini, bukan kesalahan ketik. `isBaselineSeed: true` berarti ini adalah sinkronisasi pertama setelah menghubungkan, yang hanya mencatat daftar pengikut awal dan tidak pernah mengirim DM penjangkauan (jadi `dmsSent` selalu `0` pada proses tersebut).

Panggilan pertama untuk sebuah akun mungkin memakan waktu cukup lama (menelusuri daftar pengikut lengkap); panggilan berikutnya lebih cepat karena hanya pengikut baru yang dibandingkan. `404` berarti akun tidak terhubung; `412` berarti koneksi belum selesai diinisialisasi - tunggu dan coba lagi.

---

## LINE

LINE adalah saluran paling sederhana untuk dihubungkan karena tidak ada pengalihan browser atau polling. Pelanggan membuat saluran Messaging API di konsol LINE Developers, menyalin dua nilai, dan Anda mengirimkannya dalam satu panggilan. Anda kemudian memberikan kembali URL webhook kepada mereka untuk ditempelkan ke dalam konsol.

### Langkah 1 - Hubungkan dengan kredensial saluran

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

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `channel_access_token` | Ya | Token akses saluran Messaging API jangka panjang Akun Resmi. Digunakan untuk mengirim dan menerima pesan. |
| `channel_secret` | Ya | Rahasia saluran Messaging API, digunakan untuk memverifikasi tanda tangan acara masuk. |
| `channel_id` | Tidak | ID saluran numerik. Hanya untuk informasi. |

**Respons**

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

Dua bidang penting untuk apa yang Anda lakukan selanjutnya:

- **`webhook_url`** - pelanggan harus menempelkan ini ke dalam bidang **Webhook URL** saluran LINE mereka di konsol LINE Developers (dan aktifkan "Use webhook"). Sampai mereka melakukannya, tidak ada pesan masuk yang akan diterima. Tampilkan ini kepada mereka dengan jelas.
- **`chat_mode_ok`** - ketika `false`, Akun Resmi berada dalam mode "chat" dan tidak akan menerima atau mengirim pesan sampai diubah ke mode "bot" di LINE Official Account Manager. Batasi proses onboarding Anda pada tanda ini dan beri tahu pelanggan untuk mengubah modenya.

> `channel_access_token` dan `channel_secret` tidak pernah dikembalikan oleh titik akhir mana pun. Simpan di sisi Anda jika Anda membutuhkannya lagi; jika tidak, tempel ulang dari konsol LINE.

`bot_user_id` yang dikembalikan di sini adalah pengidentifikasi koneksi yang Anda gunakan dalam panggilan status, verifikasi, dan pemutusan sambungan di bawah.

### Langkah 2 - Verifikasi ulang setelah pengaturan webhook

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

Setelah pelanggan selesai mengonfigurasi URL webhook dan beralih ke mode bot, panggil ini untuk memvalidasi ulang token yang tersimpan dan menyegarkan mode obrolan yang di-cache.

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

**Respons**

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

Jika `token_valid` adalah `false`, token akses yang tersimpan tidak lagi terautentikasi - minta pelanggan untuk menerbitkannya kembali di konsol dan panggil `POST /channels/line` lagi dengan token baru.

### Periksa status LINE

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

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

**Respons**

```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 tidak memiliki feed status langsung, jadi `live` di sini selalu `false` - nilai-nilai tersebut mencerminkan status yang ditangkap pada saat terhubung (atau verifikasi terakhir).

### Putuskan sambungan LINE

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

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

**Respons**

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

---

## Viber

Viber terhubung dengan cara yang sama seperti LINE - tempel token autentikasi bot dari Panel Admin Viber dalam satu panggilan - dengan satu perbedaan yang perlu diketahui: menghubungkan juga MENDAFTARKAN webhook kami pada bot Anda saat itu juga, jadi tidak ada langkah konsol terpisah setelahnya. Itu juga berarti upaya koneksi bisa gagal jika ingress kami tidak dapat menjawab pemeriksaan webhook sinkron Viber, bukan hanya jika token itu sendiri salah.

### Langkah 1 - Hubungkan dengan token autentikasi bot

```
POST /channels/viber
```

| Kolom | Wajib | Deskripsi |
|---|---|---|
| `auth_token` | Ya | Token autentikasi bot, dari Panel Admin Viber (Pengaturan Bot Saya). |

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

**Respons**

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

Token autentikasi tidak pernah ditampilkan kembali oleh endpoint mana pun - simpan di sisi Anda jika Anda perlu menempelkannya kembali. `bot_id` adalah pengidentifikasi koneksi yang digunakan oleh panggilan status, verifikasi, dan pemutusan koneksi di bawah.

### Periksa status Viber

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

Melaporkan status koneksi yang tersimpan. Tambahkan `?live=true` untuk juga memeriksa ulang bot terhadap Viber dan menyegarkan pendaftaran webhook yang di-cache - berguna sebelum berasumsi bahwa bot yang diam sebenarnya rusak.

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

**Respons**

```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` berarti webhook bot tidak lagi mengarah ke kami - pesan masuk tidak akan sampai. Ini biasanya berarti alat lain menghubungkan bot yang sama setelahnya (pendaftaran webhook Viber bersifat last-write-wins). Perbaiki dengan panggilan verifikasi ulang di bawah, tidak perlu meminta pelanggan untuk menempelkan kembali token mereka. `live` adalah `false` saat respons merupakan status cache terakhir alih-alih pemeriksaan baru terhadap Viber.

### Daftarkan ulang webhook

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

Tindakan perbaikan untuk `webhook_ok: false` - mendaftarkan ulang webhook kami pada bot menggunakan token autentikasi yang sudah tersimpan.

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

**Respons**

```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` berarti token yang tersimpan tidak lagi berfungsi - hubungkan kembali dengan `POST /channels/viber` dan token baru.

### Memutuskan Viber

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

Membatalkan pendaftaran webhook kami di sisi Viber (upaya terbaik) dan menghapus koneksi.

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

**Respons**

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

---

## TikTok

> **Ketersediaan:** Beta dengan ketersediaan terbatas, diaktifkan per akun. Menghubungkan TikTok akan menghasilkan kesalahan izin sampai akun diaktifkan untuk fitur tersebut.

TikTok Business Messaging adalah saluran OAuth penuh seperti Meta, tetapi lebih sederhana di sisi polling: tidak ada langkah polling status khusus untuk dibangun, karena akun yang terhubung muncul dengan sendirinya setelah TikTok mengalihkan kembali dan koneksi ditulis. Titik akhir status di bawah ini ada untuk mengonfirmasi status sesuai permintaan (alat pendukung, pemeriksaan kesehatan), bukan sebagai sesuatu yang perlu Anda lakukan berulang kali saat menghubungkan.

### Langkah 1 - Memulai koneksi TikTok

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

Tidak memerlukan kredensial - pemegang akun memberikan otorisasi sepenuhnya di browser mereka.

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

**Respons**

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

Buka `oauth_url` di browser pemegang akun agar mereka dapat masuk ke TikTok dan menyetujui akses. Status kedaluwarsa pada `expires_at` (sekitar 30 menit) - jika sudah lewat, mulai dari awal. Tidak ada pintasan halaman yang dihosting `connect_url` untuk TikTok; membuka `oauth_url` sendiri adalah satu-satunya cara.

### Memeriksa status TikTok

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

`openId` adalah open_id Akun Bisnis TikTok, yang diketahui setelah callback OAuth dijalankan.

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

**Respons**

```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 tidak memiliki pemeriksaan kesehatan langsung yang murah, jadi `live` selalu `false` di sini - kolom-kolom tersebut mencerminkan apa yang ditulis oleh koneksi (atau penyegaran token terakhir). `status: "reauth_required"` dengan `status_reason` yang diatur berarti akun perlu melalui proses koneksi lagi; token TikTok disegarkan secara otomatis dalam rotasi tahunan, dan inilah yang muncul jika rotasi tersebut gagal.

### Memutuskan TikTok

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

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

**Respons**

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

---

## GoHighLevel

GoHighLevel (GHL) adalah integrasi CRM, bukan saluran perpesanan - menghubungkannya tidak akan menghabiskan slot saluran pada paket, karena integrasi ini menggunakan saluran yang sudah ada pada akun alih-alih menambahkan yang baru. Ini juga satu-satunya integrasi di halaman ini yang dapat menampung **lebih dari satu koneksi sekaligus**: setiap sub-akun GHL ("lokasi") tempat pelanggan menginstal aplikasi akan mendapatkan entri tersendiri.

### Langkah 1 - Memulai koneksi GHL

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

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `brand` | Tidak | Listing marketplace GHL mana yang akan diotorisasi. Default-nya adalah listing standar - hanya relevan jika deployment Anda memiliki lebih dari satu aplikasi marketplace yang dikonfigurasi. |

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

**Respons**

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

Buka `oauth_url` di browser pemilik akun agar mereka dapat memilih lokasi GHL dan menyetujui akses. Status ini akan kedaluwarsa pada `expires_at` (sekitar 30 menit).

### Mencantumkan koneksi GHL

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

Tidak seperti saluran lain, ini bukan status satu koneksi saja - ini mencantumkan setiap lokasi yang telah dihubungkan oleh akun tersebut.

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

**Respons**

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

### Memutuskan koneksi lokasi GHL

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

Menghapus koneksi di sini, yang akan menghentikan setiap sinkronisasi dan pemicu untuk lokasi tersebut. Ini tidak menghapus instalan aplikasi di sisi GHL - pelanggan harus menghapusnya dari instalasi marketplace GHL mereka jika mereka menginginkannya.

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

**Respons**

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

---

## Nomor telepon (beli dan lepas)

Alih-alih menghubungkan nomor yang sudah ada, Anda dapat membeli nomor baru yang mendukung WhatsApp secara langsung. Cari nomor yang tersedia, beli satu, lalu lakukan polling hingga proses penyediaan selesai.

::: note
**Catatan:** Nomor yang dibeli di sini mendukung WhatsApp. Pendaftaran pengirim WhatsApp berjalan di latar belakang setelah pembelian, jadi Anda perlu melakukan polling status hingga mencapai `ONLINE` sebelum mengirim. Kredit akan dipotong saat pembelian dan **tidak** dikembalikan saat Anda melepaskan nomor tersebut.
:::


### Langkah 1 - Cari nomor yang tersedia

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

| Parameter kueri | Wajib | Deskripsi |
|---|---|---|
| `country_code` | Ya | Kode negara ISO 3166-1 alpha-2 untuk pencarian (misalnya `US`, `GB`, `NL`). |
| `type` | Tidak | Kelas nomor yang diinginkan, `local` atau `mobile`. Kedua kelas mungkin tetap akan dikembalikan. |

**Respons**

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

Setiap hasil menunjukkan `purchase_credits` satu kali dan `monthly_credits` berulang. Nomor yang disediakan platform berharga setidaknya 50 kredit per bulan, meningkat sesuai harga bulanan operator itu sendiri, yang dibebankan saat pembelian dan pada setiap perpanjangan. Gunakan `purchase_credits` / `monthly_credits` yang dikembalikan oleh pencarian; jangan pernah menentukan harga sendiri. Pencarian pertama pada akun baru menyediakan beberapa sumber daya dasar, sehingga mungkin sedikit lebih lambat daripada pencarian berikutnya.

### Langkah 2 - Membeli nomor

```
POST /phone-numbers
```

Gunakan `phone_number` dari hasil pencarian.

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

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `phone_number` | Ya | Nomor yang dikembalikan oleh pencarian nomor yang tersedia, dalam format E.164. |
| `country_code` | Ya | Kode negara ISO 3166-1 alpha-2 (contoh: `US`). |
| `display_name` | Tidak | Label yang mudah diingat. Default-nya adalah nomor telepon. |
| `category` | Tidak | Label kategori opsional. |

**Respons**

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

Nomor dimulai dalam status `PURCHASED`. Pendaftaran WhatsApp kemudian berlanjut di latar belakang: `PURCHASED` -> `PENDING` -> `ONLINE`.

> Jika pembelian gagal karena alamat bisnis tidak ada atau detail wajib lainnya belum diatur, Anda akan mendapatkan `400` dengan `error` yang deskriptif. Atur detail yang kurang tersebut dan coba lagi.

### Langkah 3 - Lakukan polling hingga ONLINE

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

Ini adalah endpoint status nomor telepon bersama - ini berfungsi untuk nomor WhatsApp yang dibeli maupun nomor Anda yang lain yang terhubung.

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

**Respons**

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

### Langkah 4 - Melepaskan nomor

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

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

**Respons**

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

Apa yang dilakukan hal ini bergantung pada milik siapa nomor tersebut.

Untuk nomor yang **disewa melalui platform**, ini adalah pelepasan yang sebenarnya: pengirim WhatsApp dibatalkan pendaftarannya, nomor dikembalikan ke operator dan dihapus dari akun, masa tunggu 7 hari diterapkan di mana nomor tersebut tidak dapat dibeli kembali oleh siapa pun, dan tidak ada kredit yang dikembalikan.

Untuk nomor yang **dibawa sendiri oleh akun** (akun Twilio miliknya sendiri, aplikasi Meta atau Akun WhatsApp Business miliknya sendiri, atau gateway SMS Android), panggilan yang sama hanya menghapusnya dari akun tersebut. Tidak ada yang dirilis di penyedia hulu dan tidak ada masa tunggu (cooldown) yang dicatat, sehingga nomor tersebut dapat segera dihubungkan kembali. Registrasi pengirim WhatsApp-nya, jika ada, mungkin bertahan atau tidak: proses penghapusan mencoba menghapus pengirim menggunakan kredensial Twilio yang dikelola platform akun tersebut. Pada akun yang masih menggunakan pengaturan terkelola, kredensial tersebut valid dan pengirim dihapus, sehingga menghubungkan kembali berarti mendaftarkannya lagi. Pada akun yang telah beralih ke Twilio miliknya sendiri, penghapusan tidak dapat diautentikasi, dan pengirim tetap terdaftar di akun tersebut — menghubungkan kembali berarti hanya menyambungkan kembali pengirim yang sudah ada.

### Menambahkan nomor yang sudah Anda miliki (BYO)

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

Melewati alur cari-dan-beli di atas sepenuhnya. Gunakan ini saat akun membawa nomornya sendiri (Twilio mereka sendiri, Akun WhatsApp Business Meta mereka sendiri, atau gateway SMS Android) alih-alih menyewa melalui platform. Ini hanya mencatat nomor tersebut - tidak ada kredit yang dibebankan, dan tidak ada yang diprovisikan dengan penyedia di sini. Nomor tetap tidak aktif sampai pemilik akun menyelesaikan OAuth WhatsApp untuk mendaftarkan Pengirim di nomor tersebut (alur yang sama yang dimulai oleh tombol "Bawa nomor Anda sendiri" di dasbor).

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `phone_number` | Ya | Nomor yang akan ditambahkan, dalam format E.164 (contoh: `+14155551234`). |
| `country_code` | Ya | Kode negara ISO 3166-1 alpha-2 (contoh: `US`). |
| `display_name` | Tidak | Label yang mudah diingat. Default-nya adalah nomor telepon. |
| `category` | Tidak | Label kategori opsional. |

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

**Respons** (`201 Created`):

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

`phone_number` yang bukan merupakan nomor E.164 asli (atau yang terlihat seperti nomor tes WhatsApp Meta, yang tidak pernah bisa mengirim pesan ke pelanggan asli) akan mengembalikan `400`. Menambahkan nomor yang sudah ada di akun - bahkan jika penulisannya sedikit berbeda, seperti bentuk `+52` vs `+521` di Meksiko - akan mengembalikan `409` alih-alih membuat baris duplikat.

### Menetapkan nomor sebagai utama

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

Mengubah satu nomor menjadi `is_active: true` dan setiap nomor lain di akun menjadi `is_active: false`, secara atomik - akun tidak akan pernah memiliki dua nomor aktif, atau tidak ada sama sekali, di tengah permintaan. `is_active` tidak dapat ditetapkan melalui endpoint pembaruan umum dengan sengaja; panggilan khusus ini adalah satu-satunya cara untuk mengubah nomor mana yang menjadi utama.

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

**Respons**

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

`phone_number` di sini adalah objek nomor lengkap (bentuk yang sama yang dikembalikan `GET /phone-numbers`), bukan hanya string. `phoneNumber` yang tidak ada di akun akan mengembalikan `404`.

### Menghapus catatan nomor (tanpa melepaskannya)

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

Penghapusan biasa atas catatan nomor di akun ini - tidak ada pelepasan atau pembatalan pendaftaran di sisi penyedia, dan tidak ada masa tunggu 7 hari seperti yang berlaku pada langkah pelepasan di atas. Gunakan ini untuk menghapus catatan BYO, WhatsApp Web, Telegram, atau LINE, atau entri yang sudah usang, tanpa melalui alur pelepasan terkelola. Tidak seperti pelepasan, menghapus nomor yang tidak ada di akun adalah `404`, bukan keberhasilan senyap.

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

**Respons**

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

---

## Mengarahkan saluran ke kampanye

Menghubungkan saluran akan memasukkan pesan **ke dalam** akun. Hal ini tidak menentukan **AI Agent mana yang menjawabnya**.

Perutean ditangani oleh **Entry Points** pada AI Agent, bukan oleh kampanye. Setiap saluran memiliki satu Entry Point default saluran yang menamai Agen yang menjawab kontak baru yang tidak dikenal di saluran tersebut:

| Apa yang ingin Anda lakukan | Panggilan |
|---|---|
| Mengarahkan saluran ke Agen yang seharusnya menjawabnya | `PUT /entry-points/channel-defaults` dengan body `{ "channel": "instagram", "agent_id": "AGENT_ID" }` |
| Memeriksa apakah tangga Entry Points aktif untuk akun tersebut | `GET /entry-points/routing-status`, yang mengembalikan `{ "success": true, "cutover_enabled": true }` setelah Entry Points memutuskan perutean akun tersebut |
| Membiarkan saluran tanpa Agen yang menjawabnya | `DELETE /entry-points/channel-defaults?channel=instagram` |

Sampai sebuah saluran memiliki Titik Masuk (Entry Point), pesan pertama dari seseorang yang belum pernah Anda ajak bicara akan tetap tersimpan, tetapi tidak ada yang mengambilnya dan tidak ada asisten yang membalas. Ini adalah langkah yang paling sering terlewatkan oleh integrasi: menghubungkan Instagram dan membuat Agen saja tidak cukup — Anda juga harus mengarahkan saluran tersebut ke Agen. Kumpulan panggilan lengkap — termasuk satu Agen per nomor WhatsApp, kata kunci, dan aturan komentar — ada di [API Titik Masuk](entry-points.md).

`POST /channels/campaign` masih menulis peta perutean kampanye per saluran warisan, yang didokumentasikan di bawah, tetapi peta tersebut tidak lagi dikonsultasikan untuk perutean masuk di akun mana pun; peta tersebut dipertahankan hanya untuk rollback. Jangan membangun aplikasi berdasarkan peta tersebut.

### Rute satu atau beberapa saluran (peta perutean kampanye warisan)

`POST /channels/campaign`

**Bidang permintaan**

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `campaign_id` | Ya | Kampanye yang harus menjawab kontak baru di saluran ini. Harus milik akun tersebut. |
| `channels` | Ya | Array saluran yang tidak kosong untuk diarahkan. Yang diizinkan: `whatsapp`, `whatsapp_web`, `telegram`, `instagram`, `messenger`, `chat_widget`, `custom_channel`, `sms`, `email`. |

Slot perutean dan daftar `enabled_channels` kampanye diperbarui bersamaan dalam satu operasi atomik, sehingga keduanya tidak akan pernah tidak sinkron. Saluran yang sudah diarahkan ke kampanye lain cukup diarahkan ulang ke kampanye ini.

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

**Respons**

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

### Apa yang harus dipenuhi agar perutean benar-benar berjalan

Pada akun yang masih membaca peta perutean kampanye warisan, perutean berhasil sebagai panggilan API tetapi tiga hal pada kampanye menentukan apakah pesan masuk yang sebenarnya akan dijawab. Periksa ketiganya saat saluran yang dirutekan tetap diam.

| Persyaratan | Apa yang terjadi jika tidak terpenuhi |
|---|---|
| `type` adalah `Incoming from Unknown Contacts` atau `Combined` | Permintaan ditolak dengan `400`. Kampanye Keluar dan Kata Kunci tidak dapat menampung slot perutean. |
| `status` adalah `Live` | Perutean disimpan tetapi tidak pernah mengambil apa pun. Kampanye `Draft` adalah penyebab paling umum dari "Saya telah merutekannya dan tidak terjadi apa-apa". |
| `ai_mode` adalah `true` | Kontak dibuat dan pesan disimpan, tetapi asisten tidak pernah membalas. |

Pencocokan kata kunci sekarang ada pada Entry Points — buat Entry Point dengan tipe `keyword` pada AI Agent yang seharusnya menjawab.

### Satu kampanye per saluran

Setiap saluran menampung tepat satu slot perutean warisan. Merutekan kampanye kedua ke saluran yang sama akan mengarahkan ulang slot tersebut secara diam-diam dan mengembalikan `200` — tidak ada kesalahan konflik. Kampanye sebelumnya tetap menangani kontak yang sudah dimilikinya; kampanye tersebut hanya berhenti menerima kontak baru.

### Menghapus perutean saluran

`DELETE /channels/campaign/{channel}`

Menghapus perutean untuk satu saluran, apa pun kampanye yang saat ini dituju, dan mengeluarkan saluran tersebut dari `enabled_channels` kampanye itu. Kontak baru yang tidak dikenal pada saluran tersebut tidak lagi diambil oleh kampanye mana pun. Kontak yang sudah ada di dalam kampanye akan tetap berjalan seperti sebelumnya.

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

**Respons**

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

Ini bersifat idempoten: menghapus saluran yang tidak pernah dirutekan juga akan mengembalikan `200`, dengan `cleared: false` dan `campaign_id: null`. Titik akhir ini memerlukan fitur **kampanye masuk** pada paket Anda; tanpanya, Anda akan mendapatkan `403`.


---

## Gunakan aplikasi Meta Anda sendiri (Instagram + Messenger)

Secara default, koneksi Instagram + Messenger berjalan melalui aplikasi Meta platform, sehingga nama aplikasi tersebutlah yang dilihat oleh pemegang akun di layar persetujuan Facebook. Jika Anda ingin layar persetujuan menampilkan merek **Anda** sebagai gantinya, Anda dapat mendaftarkan aplikasi Meta Anda sendiri dan mengarahkan seluruh alur melaluinya. Setelah dikonfigurasi, ini akan berlaku untuk akun Anda — tidak ada yang berubah dalam panggilan koneksi di atas kecuali branding-nya.

> **Ini hanya mencakup Instagram + Messenger.** Koneksi WhatsApp, WhatsApp Web, Telegram, dan LINE tidak terpengaruh oleh aplikasi Meta kustom.

### Apa yang dibutuhkan aplikasi Anda terlebih dahulu

Ini adalah bagian yang memakan waktu, dan sepenuhnya terjadi di sisi Meta:

1. **Sebuah aplikasi** dengan tipe Bisnis, dengan produk Messenger dan Instagram ditambahkan.
2. **Akses Lanjutan** (melalui Tinjauan Aplikasi Meta) untuk: `pages_show_list`, `pages_messaging`, `pages_manage_metadata`, `pages_read_engagement`, `instagram_basic`, `instagram_manage_messages`. Tanpa Akses Lanjutan, hanya orang yang memiliki peran di aplikasi Anda yang dapat menyelesaikan koneksi — koneksi klien Anda akan gagal. Tinjauan Aplikasi biasanya memakan waktu beberapa minggu dan memerlukan Verifikasi Bisnis.
3. **Konfigurasi Facebook Login for Business** yang dibuat di dalam aplikasi Anda, dengan memberikan izin yang sama. ID konfigurasi numeriknya bersifat per-aplikasi, jadi Anda harus membuat milik Anda sendiri.

Jika aplikasi Anda kehilangan salah satu izin yang diperlukan, koneksi akan gagal pada saat menghubungkan dengan kesalahan yang jelas menyebutkan apa yang hilang (terlihat di polling `/status` sebagai `byo_app_missing_permissions`) — alih-alih tampak berhasil namun gagal pada pesan pertama.

### Langkah 1 - Simpan aplikasi Anda

`PUT /account-config/meta-app`

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `app_id` | Ya | ID Aplikasi Meta Anda (Pengaturan → Dasar). |
| `app_secret` | Ya | Rahasia Aplikasi Meta Anda. Diverifikasi terhadap Meta sebelum disimpan, kemudian dienkripsi. Tidak pernah dikembalikan oleh endpoint mana pun. |
| `config_id` | Ya | ID numerik dari konfigurasi Facebook Login for Business di dalam aplikasi Anda. |

Ketiganya diperlukan untuk alur Login Facebook. Jika Anda hanya menjalankan jalur push-token Login Instagram yang dijelaskan di bawah, Anda dapat mengabaikannya sepenuhnya.

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

**Respons**

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

### Langkah 2 - Konfigurasikan aplikasi Anda untuk berkomunikasi dengan kami

Di dasbor aplikasi Meta Anda:

1. **Webhook** - untuk produk Instagram maupun Messenger, atur URL Callback ke nilai `webhook_urls` yang cocok dari respons, dan token Verifikasi ke `verify_token`. Berlanggananlah ke bidang `messages`, `messaging_postbacks`, dan `comments`.
2. **URI Pengalihan OAuth yang Valid** - tambahkan `https://api.youraiconnector.com/v1/auth-meta-callback-handler` agar alur persetujuan dapat kembali.

`GET /account-config/meta-app` mengembalikan materi pengaturan yang sama kapan saja; `DELETE /account-config/meta-app` menghapus aplikasi (koneksi di masa mendatang akan kembali ke aplikasi platform — hapus juga langganan webhook di dalam aplikasi Anda).

### Langkah 3 - Hubungkan seperti biasa

Tidak ada hal lain yang berubah. `POST /channels/meta/connect` (dan halaman `connect_url` yang dihosting) secara otomatis menggunakan aplikasi Anda untuk akun Anda; `uses_byo_meta_app: true` respons mengonfirmasi aplikasi mana yang akan ditampilkan oleh layar persetujuan. Pengiriman pesan, pemilihan halaman, dan pemutusan koneksi berfungsi sama persis.

## Gunakan aplikasi Login Instagram Anda sendiri (push token)

Bagian di atas membahas alur Login Facebook, di mana akun terhubung melalui Halaman Facebook. Meta juga menawarkan **API Instagram dengan Login Instagram** (Login Bisnis untuk Instagram): pemilik akun melakukan autentikasi langsung di Instagram, tanpa melibatkan akun atau Halaman Facebook.

Jika platform Anda sudah menjalankan aplikasi Meta sendiri dengan produk tersebut, Anda sama sekali tidak memerlukan alur OAuth di pihak kami. Klien Anda mengotorisasi aplikasi **Anda**, dan Anda mengirimkan kredensial yang sudah jadi per akun kepada kami:

1. Anda menyimpan kredensial aplikasi Instagram Anda satu kali (agar kami dapat memverifikasi webhook Anda).
2. Per akun, Anda mengirimkan ID akun profesional Instagram + token pengguna Instagram berumur panjang yang diperoleh aplikasi Anda.
3. Anda mengarahkan webhook pesan Instagram aplikasi Anda ke kami. Peristiwa untuk akun yang tidak pernah Anda kirimkan akan diakui dan diabaikan.
4. Anda memiliki siklus hidup token: segarkan token di sistem Anda sendiri dan kirim setiap token yang telah disegarkan dengan panggilan yang sama. Kami tidak pernah menyegarkan token yang dikirimkan.

### Apa yang dibutuhkan aplikasi Anda terlebih dahulu

- Produk **Instagram** ("Pengaturan API dengan login Instagram") ditambahkan ke aplikasi Meta Anda. Produk tersebut memiliki **pasangan App ID dan App Secret sendiri**, terpisah dari App ID/Secret Facebook — temukan di panel pengaturan produk.
- **Akses Lanjutan** (melalui Tinjauan Aplikasi Meta) untuk `instagram_business_basic` dan `instagram_business_manage_messages` (tambahkan `instagram_business_manage_comments` jika Anda menggunakan otomatisasi komentar). Tanpanya, hanya orang dengan peran di aplikasi Anda yang dapat mengotorisasinya.

### Langkah 1 - Simpan kredensial aplikasi Instagram Anda

Endpoint yang sama seperti di atas — kirim pasangan Instagram ke `PUT /account-config/meta-app`. Bidang Facebook tidak diperlukan untuk jalur ini: kirim pasangan tersebut sendiri jika Anda hanya menjalankan Login Instagram, atau bersama dengan bidang Facebook jika Anda menjalankan keduanya. Penyimpanan selalu menjelaskan pengaturan keseluruhan, jadi set mana pun yang Anda tinggalkan akan dihapus.

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `instagram_app_id` | Bersama | App ID numerik milik produk Instagram itu sendiri (bukan App ID Facebook). |
| `instagram_app_secret` | Bersama | App Secret milik produk Instagram itu sendiri. Dienkripsi saat disimpan, tidak pernah dikembalikan. |

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

**Respons** — membawa URL webhook Login Instagram (URL `instagram` dan `messenger` hanya muncul jika bidang Facebook juga disimpan):

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

Di panel **Webhook** aplikasi Anda untuk produk Instagram, atur Callback URL ke `webhook_urls.instagram_login`, Verify token ke `verify_token`, dan berlangganan ke bidang `messages` dan `comments`.

### Langkah 2 - Push token per akun

`PUT /channels/instagram-login/token`

Bekerja dengan `sub_account_id` seperti rute lainnya, sehingga kunci agensi dapat menyediakan seluruh armadanya.

| Bidang | Wajib | Deskripsi |
|---|---|---|
| `ig_user_id` | Ya | **ID akun profesional Instagram** — bidang `user_id` dari `GET https://graph.instagram.com/v21.0/me?fields=user_id,username`. Ini adalah ID yang sama yang dibawa webhook Instagram sebagai `entry.id`. ⚠️ Ini **bukan** bidang `id` dari `/me` — bidang tersebut dicakup oleh aplikasi dan berbeda di setiap aplikasi Meta. Mengirimkan ID yang dicakup aplikasi akan mengembalikan `400` yang menyebutkan kesalahan tersebut. |
| `access_token` | Ya | Token pengguna Instagram berumur panjang yang diperoleh aplikasi Anda untuk akun tersebut. Divalidasi secara langsung terhadap Instagram sebelum disimpan: token harus berfungsi dan harus milik `ig_user_id`. |
| `expires_at` | Tidak | Kedaluwarsa ISO-8601 dari token. Sebagai alternatif, kirim `expires_in` (detik). Default-nya adalah 60 hari. |
| `username` | Tidak | @handle akun; kami tetap membacanya dari 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"
  }'
```

**Respons**

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

Sebagai bagian dari proses push, kami melanggan aplikasi Anda ke webhook akun tersebut (`subscribed_apps` dengan token yang dikirimkan), sehingga pesan mulai mengalir tanpa panggilan tambahan di pihak Anda.

**Penyegaran** - kirim token yang disegarkan ke titik akhir yang sama dengan `ig_user_id` yang sama; ini memperbarui token dan masa berlaku yang tersimpan di tempat.

**Konflik** - satu akun Instagram tidak pernah aktif di dua koneksi. Jika akun tersebut sudah terhubung di tempat lain, atau pada akun ini melalui alur Halaman Facebook, push akan mengembalikan `409` yang memberi tahu Anda koneksi mana yang harus diputuskan terlebih dahulu. Koneksi alur Facebook tidak pernah diganti secara otomatis, karena koneksi tersebut mungkin juga melayani Messenger.

### Langkah 3 - Putuskan koneksi saat klien keluar

`DELETE /channels/instagram-login/token` (autentikasi dan `sub_account_id` yang sama) berhenti berlangganan webhook dengan upaya terbaik dan menghapus kredensial yang tersimpan. Ini selalu berhasil, bahkan ketika token sudah kedaluwarsa — dan setelah kredensial hilang, peristiwa webhook akun tersebut akan diabaikan.

---

## Tips untuk membangun wrapper yang andal

- **Lakukan polling dengan hati-hati.** Setiap beberapa detik sudah cukup. Berhentilah setelah Anda mencapai status terminal (`connected` / `ONLINE`, atau status kegagalan), dan tetapkan batas waktu keseluruhan yang masuk akal pada loop (langkah browser/QR akan kedaluwarsa, lihat masing-masing `expires_at`).
- **URL-encode nomor telepon di path.** Awalan `+` harus dikirim sebagai `%2B`. Endpoint juga dapat memulihkan digit mentah, tetapi encoding adalah default yang aman.
- **Jangan pernah mengharapkan rahasia dikembalikan.** Token akses, rahasia saluran, dan token halaman diterima atau disimpan tetapi tidak pernah dikembalikan dalam respons apa pun.
- **Tangani gerbang otentikasi.** `403` berarti akses API tidak ada dalam paket, atau saluran yang Anda hubungkan tidak termasuk dalam paket akun. Lihat [Akses API](../integrations/api-access.md).
- **Perhatikan batas kecepatan.** Permintaan terautentikasi dibatasi hingga 300 per menit; `429` berarti berhenti sejenak dan coba lagi. Lihat [Otentikasi](authentication.md).

## Langkah berikutnya

- [Otentikasi](authentication.md) - empat bentuk otentikasi yang diterima dan format kesalahan.
- [Akses API](../integrations/api-access.md) - membuat dan mengelola kunci API Anda.
