Agent Inbox API — Baca dan Kirim Pesan Inbox WhatsApp
Agent Inbox API memberi API key akses ke Inbox WhatsApp. AI Agent atau automation tool dapat membaca percakapan dan mengirim pesan lewat API ini. AI Agent juga dapat mengembalikan percakapan ke tim Anda, berdampingan dengan agent manusia di Inbox yang sama.
Ini adalah API terpisah dari Agent API v2. Tambahkan scope Inbox ke API key workspace mana pun, termasuk key yang sudah punya scope Agent API v2.
Scope
Buat API key di Settings → API Keys, lalu tambahkan salah satu atau kedua scope Inbox. Scope ditetapkan saat key dibuat.
| Scope | Akses |
|---|---|
inbox.read | Membaca percakapan, pesan, dan template yang sudah disetujui. |
inbox.write | Mengirim pesan, menandai percakapan terbaca, mengubah pemilik atau status, menambah label, dan menambah catatan. |
Opsi key
Atur opsi ini pada key, bukan pada tiap request.
- Daftar koneksi: batasi key ke satu atau beberapa koneksi WhatsApp. Kosongkan agar key berlaku untuk semua koneksi workspace. Setiap route hanya mengembalikan atau menerima percakapan pada koneksi yang diizinkan.
- Visibilitas nomor: sembunyikan nomor telepon customer pada setiap response. Nomor yang disembunyikan menyisakan 5 digit awal dan 3 digit akhir. Contoh:
628123456789menjadi62812****789.
Autentikasi
Kirim key sebagai bearer token pada setiap request.
Authorization: Bearer <api_key_anda>
| Status | Arti |
|---|---|
401 | Key tidak ada, salah, kedaluwarsa, sudah dicabut, atau tidak punya scope yang dibutuhkan. |
403 | Paket Anda tidak mengizinkan akses ini. |
503 | Inbox belum tersedia untuk workspace ini. |
Pemilik percakapan
Setiap percakapan punya satu owner: human, atau agent:<api_key_id> untuk key agent.
- Percakapan baru mendapat pemilik secara otomatis. Konektor memilih key aktif dengan scope
inbox.writepaling lama yang mengizinkan koneksi tersebut. Tidak ada key yang cocok membuat pemilik tetaphuman. - Key Anda hanya bisa mengirim pesan pada percakapan yang ia miliki. Mengirim pesan pada percakapan milik
humanatau agent lain mengembalikan409 OWNER_MISMATCH. - Pesan dari anggota tim selalu mengembalikan percakapan ke
human. - Key Anda juga bisa meminta pengalihan langsung. Lihat Update percakapan. Key hanya boleh mengatur
ownerkehumanatau keagent:<api_key_id>miliknya sendiri, tidak pernah ke id agent lain. - Setiap perubahan pemilik memicu event webhook
inbox.conversation.owner_changed.
Kanal unofficial butuh persetujuan aktif dari salah satu anggota tim sebelum key Anda bisa mengirim pesan di sana. Pengiriman tanpa itu mengembalikan 409 ACKNOWLEDGEMENT_REQUIRED.
Objek percakapan
{
"id": "7c9ecb52-1f2a-4b3f-9b3e-2b6a2c8f9a11",
"connection_id": "conn_abc123",
"channel": "waba",
"owner": "agent:ak_9f21",
"status": "open",
"assigned_to_user_id": null,
"label_ids": ["vip"],
"unread_count": 1,
"window_expires_at": "2026-09-17T14:00:00.000Z",
"snoozed_until": null,
"last_message_at": "2026-09-17T09:58:00.000Z",
"updated_at": "2026-09-17T09:58:01.000Z",
"contact": { "name": "Budi", "phone": "628123456789" }
}
| Field | Arti |
|---|---|
channel | waba (Cloud API resmi), unofficial (sesi QR), atau partner (nomor dari partner yang terhubung). |
owner | human atau agent:<api_key_id>. Lihat Pemilik percakapan. |
status | open, pending, snoozed, resolved, atau closed. |
window_expires_at | Waktu jendela percakapan 24 jam berakhir. null bila sudah berakhir. |
contact.phone | Disembunyikan bila key Anda memakai visibilitas nomor tersembunyi. |
Objek pesan
{
"id": "msg_9f2a1b",
"external_id": "wamid.HBgMNjI4MTIzNDU2Nzg5FQIAERgS",
"direction": "outbound",
"kind": "text",
"text": "Terima kasih, pesanan Anda sedang dikirim.",
"media": null,
"status": "sent",
"error_code": null,
"actor": { "type": "agent", "id": "ak_9f21" },
"occurred_at": "2026-09-17T09:58:00.000Z",
"referral": null
}
| Field | Arti |
|---|---|
direction | inbound (dari customer) atau outbound (ke customer). |
kind | text, template, image, video, audio, document, location, atau system. Anda hanya bisa mengirim text atau template. |
media | Selalu null. Field kind menunjukkan jenis pesan. Konektor tidak mengirim isi media lewat API ini. |
status | pending, sent, delivered, read, atau failed. |
actor | { "type": "agent", "id": "<api_key_id>" }, { "type": "user", "id": "<user_id>" }, atau null untuk pesan masuk. |
referral | Detail iklan click-to-WhatsApp untuk pesan yang membuka percakapan, atau null. |
referral.ctwa_clid | ID klik iklan, atau null. |
referral.source_id | ID iklan atau post, atau null. |
referral.source_type | Jenis sumber iklan, atau null. |
referral.source_url | URL sumber iklan, atau null. |
referral.headline | Judul teks iklan, atau null. |
Ringkasan route
| Method | Path | Scope | Keterangan |
|---|---|---|---|
GET | /api/v1/inbox/conversations | inbox.read | Daftar percakapan |
GET | /api/v1/inbox/conversations/{id} | inbox.read | Ambil satu percakapan |
GET | /api/v1/inbox/conversations/{id}/messages | inbox.read | Daftar pesan, dari yang terlama |
POST | /api/v1/inbox/conversations/{id}/messages | inbox.write | Kirim pesan text atau template |
POST | /api/v1/inbox/conversations/{id}/read | inbox.write | Tandai percakapan terbaca |
PATCH | /api/v1/inbox/conversations/{id} | inbox.write | Ubah pemilik, status, atau label, atau tambah catatan |
GET | /api/v1/inbox/templates | inbox.read | Daftar template yang disetujui |
Percakapan di luar daftar koneksi key Anda mengembalikan 404 NOT_FOUND pada setiap route.
Daftar percakapan
GET /api/v1/inbox/conversations
Scope: inbox.read
| Query parameter | Keterangan |
|---|---|
connection_id | Batasi hasil ke satu koneksi. |
owner | human, agent (agent mana pun), atau agent:<api_key_id>. |
status | Satu status percakapan. |
updated_after | ISO date-time. Hanya percakapan yang diupdate setelah waktu ini. |
limit | 1-100. Default 30. |
cursor | Dari response sebelumnya. Kosongkan untuk halaman pertama. |
{
"conversations": [ { "id": "7c9ecb52-...", "...": "..." } ],
"cursor": "eyJ0IjoxNzU4MDk1..."
}
Panggil route ini lagi dengan cursor diisi nilai yang dikembalikan, untuk membaca halaman berikutnya. Cursor null berarti tidak ada halaman berikutnya.
Ambil satu percakapan
GET /api/v1/inbox/conversations/{id}
Scope: inbox.read. Mengembalikan { "conversation": { ... } }.
Daftar pesan
GET /api/v1/inbox/conversations/{id}/messages
Scope: inbox.read
| Query parameter | Keterangan |
|---|---|
limit | 1-100. Default 50. |
before | ISO date-time. Hanya pesan yang terjadi sebelum waktu ini. |
{
"messages": [ { "id": "msg_1", "...": "..." } ],
"has_more": false
}
Pesan datang dari yang terlama. Untuk membaca pesan yang lebih lama, panggil lagi dengan before diisi nilai occurred_at dari pesan terlama yang sudah Anda punya.
Kirim pesan
POST /api/v1/inbox/conversations/{id}/messages
Scope: inbox.write. Kirim header Idempotency-Key pada setiap request.
Idempotency-Key: <nilai unik untuk pengiriman ini>
Ulangi request dengan Idempotency-Key yang sama setelah timeout atau error jaringan. Konektor hanya mengirim pesan satu kali. Header yang hilang mengembalikan 400 IDEMPOTENCY_KEY_REQUIRED.
Kirim pesan text saat jendela percakapan 24 jam masih terbuka. Field text menerima maksimal 16.384 karakter:
{
"kind": "text",
"text": "Terima kasih, pesanan Anda sedang dikirim.",
"preview_url": true
}
Kirim template yang sudah disetujui untuk membuka atau memulai ulang percakapan. Kirim maksimal 50 nilai body_params, masing-masing maksimal 2.048 karakter:
{
"kind": "template",
"template": {
"name": "order_confirmation",
"language": "id",
"body_params": ["Budi", "INV-2049"]
}
}
Urutkan body_params sesuai urutan placeholder. Setiap nilai mengisi satu placeholder secara berurutan: {{1}}, {{2}}, dan seterusnya. Lihat Daftar template untuk jumlah placeholder tiap template.
Kedua bentuk request mengembalikan 202 Accepted:
{ "message_id": "msg_9f2a1b", "status": "sent" }
status bernilai sent atau failed. Status pengiriman berikutnya datang lewat webhook inbox.message.status. Idempotency-Key yang sama mengembalikan hasil pertama, termasuk saat hasilnya failed. Pakai key baru untuk mengirim ulang.
kind: "interactive" tidak didukung dan mengembalikan 422 UNSUPPORTED_KIND. Kirim text atau template sebagai gantinya.
Tandai percakapan terbaca
POST /api/v1/inbox/conversations/{id}/read
Scope: inbox.write. Mengembalikan { "id": "7c9ecb52-...", "unread_count": 0 }.
Update percakapan
PATCH /api/v1/inbox/conversations/{id}
Scope: inbox.write. Kirim minimal satu field.
| Field | Keterangan |
|---|---|
owner | human atau agent:<api_key_id> milik Anda sendiri. Id agent lain mengembalikan 403 OWNER_FORBIDDEN. |
status | Status percakapan yang baru. |
label_ids | Maksimal 20 id label. |
note | 1-4096 karakter. Menambah catatan internal. Catatan tidak terkirim sebagai pesan ke customer. |
Ambil alih percakapan:
{ "owner": "agent:ak_9f21" }
Kembalikan ke tim Anda:
{ "owner": "human" }
Mengembalikan { "conversation": { ... } } dengan kondisi terbaru.
Daftar template
GET /api/v1/inbox/templates
Scope: inbox.read. Query parameter opsional: connection_id.
{
"templates": [
{
"id": "tpl_1",
"connection_id": "conn_abc123",
"name": "order_confirmation",
"language": "id",
"category": "UTILITY",
"body": "Halo {{1}}, pesanan Anda #{{2}} sudah kami terima.",
"parameter_count": 2
}
]
}
Hanya template yang sudah disetujui yang muncul. parameter_count adalah jumlah nilai body_params yang dibutuhkan saat mengirim.
Yang Tidak Didukung API Ini
- Pesan interactive (tombol dan list). Kirim
textatautemplatesebagai gantinya. - Parameter header template. Hanya parameter body yang tersedia.
- Isi media, baik pada pesan maupun payload webhook. Field
kindmenunjukkan jenisnya. - Indikator sedang mengetik.
POST .../readhanya menandai percakapan terbaca.
Format Error
Setiap error mengembalikan body JSON dengan field code.
{
"statusCode": 409,
"statusMessage": "OWNER_MISMATCH",
"data": { "code": "OWNER_MISMATCH" }
}
Baca data.code untuk menentukan penanganan error di sisi Anda.
| Status | Code | Arti |
|---|---|---|
| 400 | INVALID_QUERY | Query parameter tidak sesuai tipe atau rentang yang diharapkan. |
| 400 | INVALID_REQUEST | Body request tidak sesuai bentuk yang diharapkan. |
| 400 | IDEMPOTENCY_KEY_REQUIRED | Header Idempotency-Key tidak ada. |
| 401 | — | Key tidak ada, salah, kedaluwarsa, sudah dicabut, atau tidak punya scope yang dibutuhkan. |
| 403 | — | Paket Anda tidak mengizinkan akses ini. |
| 403 | OWNER_FORBIDDEN | Anda mencoba mengatur owner ke id agent lain. |
| 404 | NOT_FOUND | Percakapan tidak ada, atau daftar koneksi key Anda tidak mengizinkannya. |
| 409 | OWNER_MISMATCH | Key Anda bukan pemilik percakapan ini. |
| 409 | CONNECTION_UNAVAILABLE | Koneksi WhatsApp belum siap mengirim. |
| 409 | ACKNOWLEDGEMENT_REQUIRED | Kanal unofficial butuh persetujuan aktif dari salah satu anggota tim. |
| 409 | NOT_RETRYABLE | Pesan ini tidak bisa dicoba ulang. |
| 422 | UNSUPPORTED_KIND | Field kind pesan bernilai interactive. |
| 422 | WINDOW_CLOSED | Jendela percakapan 24 jam sudah tertutup. Kirim template sebagai gantinya. |
| 422 | TEMPLATE_NOT_APPROVED | Tidak ada template disetujui yang cocok dengan nama dan bahasa ini. |
| 422 | INVALID_MESSAGE | Pesan tidak lolos validasi. |
| 502 | DELIVERY_FAILED | WhatsApp gagal mengirim pesan ini. |
| 503 | WHATSAPP_INBOX_UNAVAILABLE | Inbox belum tersedia untuk workspace ini. |
Idempotensi dan Rate Limit
Kirim header Idempotency-Key yang unik pada setiap pengiriman pesan. Pakai nilai yang sama saat mencoba ulang. Konektor hanya mengirim pesan satu kali untuk key yang sama.
Batasnya 300 request per menit. Di atas itu API menjawab 429. Andalkan Idempotency-Key agar percobaan ulang tidak pernah mengirim pesan dua kali.
Event Webhook Inbox
Selain event lead.*, Inbox mengirim empat event lewat webhook yang sama seperti di halaman Webhooks. Header, verifikasi signature, dan pengiriman memakai mekanisme yang sama. Body event membungkus payload:
{ "event": "<nama_event>", "payload": { "...": "..." } }
Ini berbeda dari event lead.*, yang body-nya adalah payload itu sendiri.
inbox.message.received
Terpicu saat pesan dari customer masuk.
{
"event": "inbox.message.received",
"payload": {
"conversation": {
"id": "7c9ecb52-...",
"connection_id": "conn_abc123",
"channel": "waba",
"owner": "agent:ak_9f21",
"status": "open",
"window_expires_at": "2026-09-17T14:00:00.000Z"
},
"contact": { "phone": "628123456789", "name": "Budi" },
"message": {
"id": "msg_3",
"external_id": "wamid.HBg...",
"kind": "text",
"text": "Pesanan saya sudah dikirim belum?",
"media": null,
"occurred_at": "2026-09-17T10:02:00.000Z"
},
"referral": null
}
}
inbox.message.sent
Terpicu untuk setiap pesan keluar, termasuk yang dikirim key Anda sendiri. Bandingkan actor.id dengan id key Anda untuk melewati pesan Anda sendiri.
{
"event": "inbox.message.sent",
"payload": {
"conversation": { "id": "7c9ecb52-...", "connection_id": "conn_abc123", "channel": "waba", "owner": "agent:ak_9f21" },
"message": { "id": "msg_4", "kind": "text", "text": "Sudah, nomor resi ada di email Anda.", "status": "sent", "occurred_at": "2026-09-17T10:03:00.000Z" },
"actor": { "type": "agent", "id": "ak_9f21" }
}
}
inbox.message.status
Terpicu saat status pesan berubah, misalnya menjadi delivered, read, atau failed.
{
"event": "inbox.message.status",
"payload": {
"conversation_id": "7c9ecb52-...",
"message_id": "msg_4",
"status": "delivered",
"error_code": null,
"at": "2026-09-17T10:03:05.000Z"
}
}
inbox.conversation.owner_changed
Terpicu saat pemilik percakapan berubah, baik lewat aksi anggota tim maupun PATCH dari key Anda.
{
"event": "inbox.conversation.owner_changed",
"payload": {
"conversation_id": "7c9ecb52-...",
"owner": "human",
"actor": { "type": "user", "id": "usr_182" },
"at": "2026-09-17T10:05:00.000Z"
}
}
Keamanan
- Jangan mengirim API key melalui prompt, URL, atau log. Simpan key di secret manager agent Anda.
- Enkripsi data percakapan atau pesan yang Anda simpan di sisi Anda.
- Minta scope
inbox.readsaja bila agent Anda hanya perlu membaca Inbox.
Langkah berikutnya
Butuh Bantuan Lebih Lanjut?
Tim kami siap membantu Anda memaksimalkan tracking iklan dan atribusi bisnis.
Coba atau lanjutkan
© 2026 Konektor. Seluruh hak cipta dilindungi.
