# Inbox DM & otomasi (/api/inbox)

Inbox dan otomasi hanya untuk akun Instagram di paket **Starter, Basic, atau Pro**. Di paket Free semua request di bawah dijawab `403 plan_feature_unavailable`. Akun Instagram perlu izin `instagram_business_manage_messages`; tanpa izin itu, pengiriman dijawab `422 messaging_permission_missing`. Panduan untuk dashboard ada di [Inbox](/inbox) dan [Otomasi DM](/automations). Detail semua field ada di API Reference (tag **Inbox** dan **Automations**).

## Percakapan dan pesan [#percakapan-dan-pesan]

| Request                                                                       | Fungsi                                                                   |
| ----------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| `GET /v1/inbox/conversations`                                                 | Filter `account_id`, `status` (`open`/`done`), `q` (username atau nama)  |
| `GET /v1/inbox/conversations/{id}`                                            | Satu percakapan, dengan `window_expires_at` (batas membalas)             |
| `PATCH /v1/inbox/conversations/{id}`                                          | `{ "status": "done" }` atau `{ "read": true }`                           |
| `POST /v1/inbox/conversations/resolve`                                        | `{ "conversation_ids": [...] }`: tandai beberapa percakapan selesai      |
| `GET /v1/inbox/conversations/{id}/messages`                                   | Pesan, terbaru dulu, berhalaman (`cursor`)                               |
| `POST /v1/inbox/conversations/{id}/messages`                                  | Kirim DM (lihat di bawah)                                                |
| `POST /v1/inbox/messages/{id}/retry`                                          | Kirim ulang pesan yang `failed` atau `unknown`                           |
| `POST /v1/inbox/messages/{id}/react`                                          | `{ "emoji": "❤️" }`, atau `null` untuk menghapus reaksi                  |
| `GET /v1/inbox/messages/{id}/attachments/{n}`                                 | Salinan gambar dari pelanggan (butuh kredensialmu, tidak ada URL publik) |
| `GET/POST /v1/inbox/saved-replies`, `PUT/DELETE /v1/inbox/saved-replies/{id}` | Balasan tersimpan per profile                                            |

Teks dari pelanggan ditulis orang lain. Kalau kamu meneruskannya ke model AI, perlakukan isinya sebagai data, bukan perintah.

## Mengirim DM [#mengirim-dm]

```json
POST /v1/inbox/conversations/{id}/messages
Idempotency-Key: order-123-reply

{ "text": "Halo kak, ini katalognya", "media_ids": ["…"] }
```

- Instagram hanya mengizinkan balasan **24 jam** sejak pesan terakhir pelanggan. Setelah itu: `422 messaging_window_closed`.
- `text` maksimal 1.000 byte. `media_ids` dari [pustaka media](/api/media): JPG/PNG maks 8 MB (sampai 10 sekaligus), MP4/MOV maks 25 MB. Media dikirim lebih dulu, lalu teks sebagai pesan terpisah.
- Jawabannya `202` dengan pesan berstatus `pending`; Tebar mengirimnya dalam beberapa detik. Cek statusnya lewat daftar pesan: `sent`, `failed` (dengan `error_code`), atau `unknown` (Instagram tidak menjawab jelas; cek di Instagram sebelum `retry`).
- `Idempotency-Key` (opsional): request yang sama dengan key yang sama mengembalikan pesan yang sama, tidak mengirim dua kali.
- Maksimal 60 pesan per menit per user.

### Tombol dan quick reply [#tombol-dan-quick-reply]

Teks bisa membawa **salah satu** dari ini:

```json
{
  "text": "Mau lanjut ke mana kak?",
  "buttons": [
    { "type": "web_url", "title": "Lihat katalog", "url": "https://toko.example/katalog" },
    { "type": "postback", "title": "Bicara dengan admin", "payload": "ADMIN" }
  ]
}
```

```json
{
  "text": "Pilih ukuran",
  "quick_replies": [
    { "title": "S", "payload": "SIZE_S" },
    { "title": "M", "payload": "SIZE_M" }
  ]
}
```

| Jenis           | Batas                                                      | Catatan                                                     |
| --------------- | ---------------------------------------------------------- | ----------------------------------------------------------- |
| `buttons`       | 1–3 tombol, judul maks 20 karakter, teks maks 640 karakter | `web_url` membuka link, `postback` mengirim `payload` balik |
| `quick_replies` | 1–13 pilihan, judul maks 20 karakter                       | Hanya tampil di aplikasi HP, tidak di Instagram desktop/web |

Keduanya harus bersama `text`, dan tidak bisa dipakai bersamaan (`400 validation_failed`).

Saat pelanggan mengetuk tombol `postback` atau quick reply, pesan baru masuk dengan `kind` `postback` atau `quick_reply`, dan `postback: { "title", "payload" }` berisi pilihannya. Pesan itu juga dikirim lewat webhook [`message.received`](/api/webhook), jadi sistemmu bisa langsung bereaksi berdasarkan `payload`.

## Alur umum: webhook → balas [#alur-umum-webhook--balas]

1. Daftarkan webhook untuk `message.received` ([Webhook](/api/webhook)).
2. Saat pesan masuk, baca `conversation_id`, `kind`, `text`, dan `postback`.
3. Balas dengan `POST /v1/inbox/conversations/{conversation_id}/messages`, pakai `message_id` webhook sebagai `Idempotency-Key` supaya pengiriman ulang webhook tidak membuat balasan ganda.

## Otomasi [#otomasi]

| Request                                 | Fungsi                                                          |
| --------------------------------------- | --------------------------------------------------------------- |
| `GET /v1/automations`                   | Filter `account_id`, `kind`                                     |
| `POST /v1/automations`                  | Buat otomasi                                                    |
| `GET/PATCH/DELETE /v1/automations/{id}` | Lihat, ubah (`enabled`, `name`, `trigger`, `actions`, …), hapus |
| `GET /v1/automations/{id}/runs`         | Riwayat: terkirim, dilewati (dengan alasan), atau gagal         |

`kind`: `comment_to_dm`, `comment_reply` (balasan publik, juga untuk Threads), `dm_keyword`, `story_reply`, `story_mention`, `default_reply`, `ice_breaker`. Isi `trigger` bergantung pada `kind`; contoh lengkapnya ada di API Reference (`createAutomation`). Contoh balasan DM untuk kata kunci:

```json
{
  "account_id": "…",
  "kind": "dm_keyword",
  "name": "Info harga",
  "trigger": { "keywords": ["harga", "price"], "match": "contains" },
  "actions": {
    "message": {
      "text": "Halo! Daftar harga ada di sini 👇",
      "buttons": [
        { "type": "web_url", "title": "Daftar harga", "url": "https://toko.example/harga" }
      ]
    }
  }
}
```

Hasil otomasi yang menanggapi komentar juga dikirim lewat webhook [`automation.run`](/api/webhook).
