# Integrasi Instagram


OmniStream terhubung ke DM Instagram menggunakan **Instagram Login OAuth** dengan **token per akun**. Setiap akun Instagram yang ditambahkan admin akan menukar kode otorisasi dengan access token-nya sendiri — tidak ada lagi model satu token Meta App global yang dipakai untuk semua akun.

> Pendekatan per-akun ini menggantikan alur Instagram Basic Display lama. Lihat riwayat commit `393f9ae` (fix Instagram integration to use Instagram Login OAuth with per-account tokens) dan `cd49b7f` (remove unused `INSTAGRAM_LOGIN_CONFIG_ID` config) di CLAUDE.md repo history untuk perubahan terkini.

> **Peran:** Hanya **Admin** yang dapat menambah atau menghapus integrasi Instagram.
> **Rute frontend:** `/integrations`

## Prasyarat

1. **Meta App** dengan produk **Instagram** (Instagram Login) aktif.
2. **Instagram Business Account** yang dihubungkan ke Facebook Page (Meta masih memerlukan hubungan Page meski pengguna tidak pernah membukanya).
3. **Instagram App ID** dan **Instagram App Secret** dari Meta App Dashboard.
4. URL callback OAuth yang dapat dijangkau publik: `https://<host-omnistream>/integrations/instagram/callback`.
5. Akses admin ke OmniStream.

## Kredensial yang dibutuhkan

Nilai berikut perlu dikonfigurasi oleh administrator server dan pada Meta App Dashboard:

| Kredensial | Asal |
|---|---|
| **Instagram App ID** | Meta App Dashboard → Instagram → Basic Display |
| **Instagram App Secret** | Meta App Dashboard → Instagram → Basic Display |
| **Meta App Secret** | Untuk verifikasi tanda tangan webhook masuk |
| **Meta Verify Token** | Nilai bebas untuk handshake verifikasi webhook Meta |

## Alur OAuth per akun

Alur pendaftaran satu akun Instagram adalah sebagai berikut:

1. Admin membuka halaman **Integrations** (`/integrations`) dan klik **+ Add Instagram Account**.
2. OmniStream membangun URL otorisasi Instagram Login berdasarkan `INSTAGRAM_APP_ID` dan callback `https://<host>/integrations/instagram/callback`.
3. Admin diarahkan ke Instagram, memilih akun yang ingin dihubungkan, dan menerima izin:
   - `instagram_business_basic`
   - `instagram_business_manage_messages`
4. Instagram memanggil kembali callback OmniStream dengan `?code=...`.
5. Backend menukar `code` dengan **access token per akun** melalui endpoint Graph (menggunakan `INSTAGRAM_APP_ID` dan `INSTAGRAM_APP_SECRET`).
6. Token, `user_id`, `username`, dan metadata lain disimpan ke tabel `integration_accounts` pada baris dengan `channel = 'instagram'`.
7. OmniStream akan mulai memakai token tersebut saat mengirim DM keluar, dan memetakan event masuk ke akun berdasarkan user ID Instagram.

## Langkah-langkah setup

### 1. Konfigurasi Meta App

1. Di [developers.facebook.com](https://developers.facebook.com/apps), buka app Anda.
2. Tambahkan produk **Instagram → Instagram Login** jika belum.
3. Di **Instagram → Basic Display**, salin **Instagram App ID** dan **Instagram App Secret**. Simpan ke konfigurasi server OmniStream Anda.
4. Pada **Valid OAuth Redirect URIs**, tambahkan:
   `https://<host-omnistream>/integrations/instagram/callback`
   serta variannya jika Anda punya environment staging.

### 2. Konfigurasi webhook Instagram

1. Di Meta App → **Instagram → Webhooks**, klik **Configure**.
2. Masukkan **Callback URL**: `https://<host-omnistream>/webhook/instagram`
3. Masukkan **Verify Token** sama dengan `META_VERIFY_TOKEN`.
4. Langganan ke event `messages` dan `messaging_postbacks`.

### 3. Mulai alur OAuth dari UI OmniStream

1. Masuk sebagai admin ke OmniStream.
2. Buka **Integrations**, klik tab **Instagram**.
3. Klik **+ Connect Instagram Account**.
4. Pilih halaman/akun pada dialog Meta dan berikan izin.
5. Setelah redirect kembali ke OmniStream, baris baru muncul di tabel Instagram Accounts dengan username yang terdeteksi.

### 4. Kirim pesan uji

1. Dari akun Instagram lain, kirim DM ke akun yang baru dihubungkan.
2. Percakapan baru akan muncul di Inbox OmniStream.
3. Balas dari Inbox; pesan keluar dikirim memakai access token per-akun yang tersimpan.
4. Jika balasan gagal, buka halaman Integrations dan lakukan **Re-authenticate** pada akun yang bermasalah — ini memicu siklus OAuth ulang tanpa menghapus riwayat percakapan.

## Model per akun: mengapa penting

Sebelum commit `393f9ae`, OmniStream menyimpan satu kredensial Instagram global yang dibagi-pakai oleh semua integration account. Akibatnya satu token kedaluwarsa bisa memadamkan seluruh saluran, dan Meta juga tidak mengizinkannya untuk Instagram Login.

Setelah commit tersebut, setiap baris di `integration_accounts` memiliki access token-nya sendiri pada `config`. Implikasi operasionalnya:

- Menghapus satu akun **tidak** mempengaruhi akun Instagram lain.
- Token kedaluwarsa hanya memadamkan satu akun; admin cukup re-authenticate akun tersebut.

## Troubleshooting

- **OAuth redirect ditolak oleh Instagram** — pastikan URL callback di Meta App Dashboard **tepat sama** dengan yang OmniStream pakai, termasuk skema `https://`. Meta ketat terhadap trailing slash.
- **Webhook verification gagal** — `META_VERIFY_TOKEN` tidak cocok. Token ini sama untuk WhatsApp, Instagram, dan Messenger karena satu Meta App.
- **HMAC `InvalidSignature` pada webhook** — **Meta App Secret** tidak cocok. Hubungi administrator untuk memperbarui konfigurasi server.
- **Token kedaluwarsa pada satu akun** — buka Integrations, pilih akun, klik **Re-authenticate** untuk memulai OAuth ulang.

## Hubungan dengan API Reference

Tag **Integrations** pada [API Reference](/api) menampilkan endpoint untuk mengelola konfigurasi saluran. Endpoint untuk `integration_accounts` Instagram memungkinkan inspeksi daftar akun yang terhubung, dengan rahasia di-mask pada respons.

:::note
Endpoint OAuth callback Instagram (`/integrations/instagram/callback`) belum terdaftar di `openapi.yaml` per status drift pada `docs-site/SCOPE.md` Bagian 2.1. Halaman ini adalah panduan user-flow, bukan referensi REST.
:::
