API & webhook
Sambungkan bot, AI, atau sistem Anda sendiri ke Karibin untuk membaca dan membalas percakapan WhatsApp, menyalurkan lead, dan menerima setiap kejadian.
API tersedia di semua paket. Setiap bulan sudah termasuk 1.000 panggilan, dan kuota tambahan bisa dibeli di halaman Tagihan. Yang dihitung hanya permintaan dari sistem Anda yang memakai API key. Memakai aplikasi, otomasi, chatbot, broadcast, dan webhook keluar tidak dihitung.
Mulai dalam tiga langkah
- Buka Pengaturan, lalu Integrasi & API, dan buat API key. Simpan key-nya, karena hanya ditampilkan sekali.
- Kirim permintaan dengan header
x-api-key: krbn_live_...ke alamat dasarhttps://karibin.com/api/v1/public. - Kalau sistem Anda perlu tahu setiap pesan masuk, tambahkan alamat webhook di halaman yang sama.
curl https://karibin.com/api/v1/public/conversations?status=OPEN \
-H "x-api-key: krbn_live_..."
Endpoint
| Metode | Alamat | Kegunaan |
|---|---|---|
| GET | /public/usage | Pemakaian kuota bulan ini |
| GET | /public/conversations | Daftar percakapan. Filter: status, bot=true, updatedSince, limit, cursor |
| GET | /public/conversations/:id | Satu percakapan beserta kontaknya |
| GET | /public/conversations/:id/messages | Pesan dari yang terlama. after=<id pesan> untuk membaca yang baru saja |
| POST | /public/conversations/:id/messages | Kirim teks: { "text": "...", "replyToId": "..." } |
| POST | /public/conversations/:id/media | Kirim gambar, video, audio, dokumen, atau stiker. Unggah file, atau { "url": "https://..." } |
| POST | /public/conversations/:id/interactive | Kirim 1 sampai 3 tombol, atau daftar 1 sampai 10 pilihan |
| POST | /public/conversations/:id/location | Kirim lokasi: { "latitude", "longitude", "name", "address" } |
| POST | /public/conversations/:id/template | Kirim template yang disetujui Meta, termasuk template ber-header gambar, video, atau dokumen |
| POST | /public/conversations/:id/handoff | Serahkan ke agen: { "agentId": "...", "note": "..." } (keduanya opsional) |
| POST | /public/conversations/:id/bot | Bot mengambil (kembali) percakapan |
| PATCH | /public/conversations/:id | Ubah status: { "status": "RESOLVED" } |
| GET | /public/contacts?phone=0812... | Cari kontak dari nomor, format lokal atau internasional |
| GET | /public/contacts/:id | Satu kontak beserta tag |
| POST | /public/leads | Salurkan lead: { "name", "phone", "email", "source" } |
Jendela 24 jam
Teks, media, tombol, dan lokasi hanya bisa dikirim dalam 24 jam sejak pesan terakhir pelanggan, sesuai aturan WhatsApp. Setiap percakapan (dan data webhook pesan) membawa windowOpen dan windowExpiresAt. Di luar jendela, permintaan langsung ditolak dengan 409 window_closed sebelum dikirim ke WhatsApp; pakai endpoint template untuk membuka percakapan lagi. Percakapan yang pelanggannya belum pernah mengirim pesan punya windowExpiresAt: null.
Kalau WhatsApp tetap menolak setelah dikirim, respons berisi status: "FAILED" dan failCode dari Meta.
Mengirim media
Unggah sebagai multipart/form-data dengan field file (opsional caption, replyToId), atau kirim JSON { "url": "https://...", "caption", "filename", "replyToId" } dan Karibin mengunduhnya dari alamat publik itu (tanpa mengikuti pengalihan, maksimal 15 detik).
| Jenis | Format | Ukuran maksimal | Keterangan (caption) |
|---|---|---|---|
| Gambar | JPG, PNG | 5 MB | Bisa, maksimal 1.024 karakter |
| Stiker | WEBP | 500 KB | Tidak bisa |
| Video | MP4, 3GP | 16 MB | Bisa |
| Audio | AAC, AMR, MP3, M4A, OGG | 16 MB | Tidak bisa |
| Dokumen | PDF, Word, Excel, PowerPoint, TXT | 16 MB | Bisa. Nama file ikut tampil |
Isi file diperiksa: file yang mengaku JPG, PNG, WEBP, PDF, atau MP4 tapi isinya lain ditolak.
Tombol dan daftar pilihan
{ "body": "Mau lanjut ke mana?", "buttons": [{ "id": "harga", "title": "Lihat harga" }, { "id": "cs", "title": "Bicara dengan CS" }] }
{ "body": "Pilih cabang terdekat", "list": { "buttonLabel": "Pilih cabang", "rows": [{ "id": "jkt", "title": "Jakarta", "description": "Jl. Sudirman 1" }] } }
Isi salah satu, buttons atau list. Batas WhatsApp berlaku apa adanya dan teks yang melewatinya ditolak, tidak dipotong: body 1.024 karakter, judul tombol 20, judul baris 24, deskripsi baris 72, label daftar 20. Id dan judul tombol harus unik. Saat pelanggan menekan pilihan, webhook message.received membawa message.interactiveReply: { "id": "harga", "title": "Lihat harga" }.
Template dengan header
{ "templateName": "promo_gambar", "languageCode": "id", "parameters": ["Budi", "50%"], "header": { "type": "image", "url": "https://cdn.anda.com/promo.jpg" } }
Sebelum dikirim, Karibin membaca template dari akun WhatsApp nomor pengirim dan memeriksa: template ada dan berstatus disetujui, jumlah parameters sama dengan isian {{1}}, {{2}} di teks, header sesuai jenisnya, dan isian tidak berisi baris baru, tab, atau lebih dari 4 spasi berturut-turut. File header diunduh langsung oleh WhatsApp dari url (harus https). Template dengan isian di teks header atau tombol URL dinamis belum didukung.
Bot atau AI milik Anda
Aktifkan Bot atau AI milik Anda sendiri di Pengaturan, lalu Integrasi & API. Setelah itu:
- Chat baru langsung dipegang bot (
botActive: true) dan belum dibagikan ke agen. Menu chatbot dan otomasi pesan masuk tidak ikut menjawab. - Bot membaca pesan lewat webhook
message.received, lalu membalas lewatPOST /messages. - Bot menyerahkan chat ke manusia dengan
POST /handoff. TanpaagentId, Karibin memakai aturan pembagian workspace (termasuk aturan per iklan). - Kalau bot diam lebih lama dari batas menit yang Anda atur setelah pesan pelanggan (bawaan 5 menit), chat otomatis dialihkan ke agen. Ini juga yang terjadi kalau bot mati atau kuota habis, jadi pelanggan tidak pernah dibiarkan menunggu.
- Begitu agen membalas chat bot, dari aplikasi maupun dari HP, bot berhenti untuk chat itu.
Webhook
Karibin mengirim POST JSON ke alamat Anda setiap kali ada kejadian. Isi pesan dikirim utuh, tanpa dipotong.
| Kejadian | Kapan |
|---|---|
message.received | Pesan pelanggan masuk (termasuk yang masuk ke HP lewat mode nomor tetap di HP) |
message.sent | Pesan keluar. origin: agent, api, automation, phone, atau system |
message.status | Terkirim, sampai, dibaca, atau gagal (dengan failCode) |
conversation.handoff | Chat diserahkan ke agen. reason: api, agent_replied, bot_timeout |
conversation.bot | Bot mengambil (kembali) chat |
conversation.status | Status percakapan berubah |
Contoh isi kiriman dan cara memeriksa tanda tangan
{
"id": "cmd_delivery_id",
"event": "message.received",
"workspaceId": "ws_...",
"createdAt": "2026-09-22T10:30:00.000Z",
"data": {
"conversation": { "id": "...", "status": "OPEN", "botActive": true, "assignedAgentId": null },
"contact": { "id": "...", "name": "Budi", "phone": "6281234567890" },
"message": { "id": "...", "direction": "INBOUND", "origin": "customer", "body": "Harga paket berapa?", "mediaUrl": null, "replyToId": null }
}
}Setiap kiriman membawa header X-Karibin-Signature: sha256=<hex>, yaitu HMAC SHA-256 dari isi mentah dengan rahasia webhook Anda, serta X-Karibin-Delivery yang bisa dipakai untuk menolak kiriman ganda.
const expected = crypto.createHmac("sha256", SECRET).update(rawBody).digest("hex");
const provided = req.headers["x-karibin-signature"].replace("sha256=", "");
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(provided))) return res.status(401).end();Untuk menolak kiriman yang diputar ulang, tolak kiriman yang createdAt-nya lebih dari 5 menit lalu (nilainya ikut ditandatangani) dan simpan id yang sudah diterima supaya kiriman ganda diabaikan.
Balas dengan status 2xx dalam 10 detik. Kalau gagal, Karibin mencoba lagi sampai 8 kali dalam sekitar satu jam. Alamat yang gagal terus 50 kiriman berturut-turut dimatikan otomatis, dan bisa diaktifkan lagi dari halaman pengaturan. Riwayat kiriman 30 hari terakhir ada di tombol Riwayat.
Kuota, batas, dan kesalahan
| Respons | Artinya |
|---|---|
401 invalid_api_key | Key salah atau sudah dicabut |
429 rate_limited | Lebih dari 10 permintaan per detik per workspace. Coba lagi sebentar |
429 too_many_failed_requests | Terlalu banyak permintaan gagal dari satu alamat IP dalam semenit (misalnya key salah). Coba lagi 1 menit kemudian |
429 api_quota_exceeded | Kuota bulan ini habis (sudah termasuk kelonggaran 10%). Tambah kuota di Tagihan |
402 subscription_readonly | Langganan tidak aktif; membaca tetap bisa, mengirim tidak |
404 conversation_not_found | Id tidak ada di workspace pemilik key |
409 window_closed | Di luar jendela 24 jam. Pakai template |
409 whatsapp_not_connected | Nomor WhatsApp percakapan itu belum tersambung ke Karibin |
400 unsupported_channel | Bukan percakapan WhatsApp |
415 unsupported_media_type, 415 content_type_mismatch | Jenis file tidak didukung, atau isinya tidak cocok dengan tipenya |
413 file_too_large | Melebihi ukuran maksimal jenis file itu |
400 caption_not_supported | Audio dan stiker tidak bisa diberi keterangan |
400 media_url_not_allowed, 422 media_url_unreachable, 422 media_url_redirect | Alamat file tidak diizinkan, tidak bisa diunduh, atau mengalihkan |
404 template_not_found, 409 template_not_approved | Template tidak ada di nomor itu, atau belum disetujui |
400 template_params_mismatch, 400 template_param_invalid | Jumlah isian salah, atau isian berisi baris baru, tab, atau spasi berlebih |
400 template_header_required, template_header_type_mismatch, template_has_no_media_header | Header tidak sesuai template |
503 templates_unavailable | Daftar template sedang tidak bisa dibaca dari WhatsApp. Coba lagi |
Setiap respons membawa header X-Karibin-Quota-Used dan X-Karibin-Quota-Limit. Pemilik dan admin menerima email saat pemakaian mencapai 80% dan 100%. Kuota direset setiap tanggal 1 (WIB).
| Kuota per bulan | Harga |
|---|---|
| 1.000 panggilan, termasuk semua paket | Rp0 |
| +10.000 panggilan | Rp349.000 |
| +100.000 panggilan | Rp1.990.000 |
| +1.000.000 panggilan | Rp4.900.000 |