Pesan & Percakapan
Messages API memungkinkan Anda mengirim pesan ke kontak mana pun, membaca kembali percakapan, mengoreksi atau menghapus pesan yang sudah Anda kirim, memberikan reaksi pada pesan, menarik utas sesi obrolan lengkap, mengekspor transkrip, dan menandai obrolan sebagai sudah atau belum dibaca — semuanya tanpa perlu membuka kotak masuk.
Semua jalur di halaman ini relatif terhadap URL dasar https://api.youraiconnector.com/v1. Setiap permintaan memerlukan kunci API Anda — lihat Autentikasi untuk daftar lengkap cara mengirimkannya. Contoh di bawah menggunakan header X-API-Key, dengan satu contoh cURL yang juga menunjukkan formulir kueri ?apiKey=.
Cara kerja pengiriman: Mengirim pesan tidak menunggu pesan tersebut sampai. API menerima pesan Anda, segera mengembalikan ID pesan, lalu mengirimkannya di latar belakang melalui saluran kontak (WhatsApp, SMS, Instagram, dan sebagainya). Untuk melacak apakah pesan benar-benar terkirim atau telah dibaca, dengarkan pembaruan status dengan Webhook — jangan melakukan polling. Respons pengiriman hanya mengonfirmasi bahwa pesan telah diterima.
Mengirim pesan
Ada dua cara untuk mengirim. Pilih yang paling sesuai dengan cara Anda mengidentifikasi kontak:
- Kirim berdasarkan ID kontak — Anda sudah mengetahui ID kontak tersebut (misalnya, Anda membuat kontak melalui API atau mendapatkannya dari webhook). Gunakan
POST /contacts/{contactId}/send-message. - Kirim berdasarkan identitas kontak — Anda mengetahui nomor telepon, ID Instagram, dll. milik kontak tersebut, tetapi bukan ID internal mereka. Gunakan
POST /contacts/senddan biarkan platform menemukan kontak yang tepat.
Keduanya mengantrekan pesan dengan cara yang sama dan mengirimkannya melalui saluran apa pun yang digunakan kontak tersebut. Anda tidak perlu memilih transportasi — platform merutekan kontak WhatsApp melalui WhatsApp, kontak SMS melalui SMS, dan seterusnya.
Keduanya juga hanya menemukan kontak yang sudah ada. Tidak satu pun panggilan yang membuat kontak baru: ID atau identitas yang tidak cocok akan dikembalikan sebagai 404, dan tidak akan menjadi kontak baru. Jadi, jika Anda mengirim pesan kepada seseorang untuk pertama kalinya, buatlah kontaknya terlebih dahulu dengan POST /contacts, atau, di WhatsApp Web, gunakan Kirim langsung ke nomor WhatsApp Web di bawah ini, yang akan membuat kontak dalam panggilan yang sama.
Kirim berdasarkan ID kontak
POST /contacts/{contactId}/send-message
| Bidang | Wajib | Deskripsi |
|---|---|---|
body |
Ya | Teks pesan yang akan dikirim, hingga 65.536 karakter. Isi yang lebih panjang dari yang diizinkan saluran dalam satu pesan (1.500 pada WhatsApp Business API dan SMS, 1.000 pada Instagram, 2.000 pada Messenger, 4.096 pada Telegram dan LinkedIn, 5.000 pada LINE, 6.000 pada TikTok, 7.000 pada Viber, 65.536 pada WhatsApp Web; tidak ada batasan pada email, widget obrolan, dan saluran kustom) dikirim sebagai beberapa pesan secara berurutan, dipisah pada jeda paragraf atau kalimat. Respons kemudian membawa messageIds untuk setiap bagian dan autoSplit: true. |
mediaUrl |
Tidak | URL file media (gambar, audio, video, dokumen) untuk dilampirkan. |
mediaContentType |
Tidak | Tipe MIME dari media yang dilampirkan, contohnya image/jpeg. Ditentukan dari ekstensi file URL jika dihilangkan (.mp3 → audio/mpeg, .pdf → application/pdf); atur ini untuk URL tanpa ekstensi. |
sendAsVoiceNote |
Tidak | Hanya WhatsApp Web, khusus audio: kirim audio sebagai pesan suara (gelembung putar). Audio yang bukan OGG/Opus dikonversi saat pengiriman. Default ke false. |
pauseBot |
Tidak | true menjeda AI untuk kontak ini saat pesan dikirim — untuk manusia yang mengambil alih. Lihat Jeda atau lanjutkan AI. |
clearIncompleteReply |
Tidak | true membuang balasan bot yang setengah jadi agar tidak dilanjutkan setelah pesan Anda. |
human_reply |
Tidak | true menandai pesan sebagai ditulis oleh seseorang di tim Anda, bukan oleh integrasi. AI kemudian memperlakukannya sebagai balasan rekan tim dalam percakapan, dan balasan yang telah diantrekan AI untuk pesan terakhir kontak akan dibatalkan agar kontak tidak menerima dua jawaban. Ini tidak menjeda AI; gunakan pauseBot untuk itu. Default ke false. |
Di LinkedIn, pesan yang Anda kirim dengan cara ini, atau dari kotak masuk, akan tetap terkirim meskipun seseorang sedang menangani utas tersebut di sisi LinkedIn. Balasan AI itu sendiri dan tindak lanjutnya akan ditahan pada utas tersebut. Balasan yang ditahan akan dihapus dari obrolan alih-alih ditampilkan sebagai gagal, karena tidak ada yang dikirim dan tidak ada kredit yang digunakan. Balasan terakhir AI sebelum menyerahkan utas kepada seseorang akan tetap terkirim.
cURL
curl -X POST "https://api.youraiconnector.com/v1/contacts/contact123/send-message" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"body": "Hi! Your appointment is confirmed for tomorrow at 10:00."
}'
JavaScript
const res = await fetch(
"https://api.youraiconnector.com/v1/contacts/contact123/send-message",
{
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
body: "Hi! Your appointment is confirmed for tomorrow at 10:00.",
}),
}
);
const data = await res.json();
console.log(data.messageId);
Python
import requests
res = requests.post(
"https://api.youraiconnector.com/v1/contacts/contact123/send-message",
headers={
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
json={"body": "Hi! Your appointment is confirmed for tomorrow at 10:00."},
)
print(res.json()["messageId"])
Respons (200 OK):
{
"success": true,
"messageId": "aB3dE5fG7hI9jK1lM2nO",
"contactId": "contact123",
"channel": "whatsapp",
"message": "Message created successfully. Delivery is being processed."
}
Kirim berdasarkan identitas kontak
POST /contacts/send
Gunakan ini jika Anda tidak memiliki ID internal kontak. Berikan body pesan ditambah salah satu dari contact_id, atau channel bersama dengan bidang identitas yang cocok dengan saluran tersebut.
| Bidang | Wajib | Deskripsi |
|---|---|---|
body |
Ya | Teks pesan yang akan dikirim, hingga 65.536 karakter. Isi yang lebih panjang dari yang diizinkan saluran dalam satu pesan (1.500 pada WhatsApp Business API dan SMS, 1.000 pada Instagram, 2.000 pada Messenger, 4.096 pada Telegram dan LinkedIn, 5.000 pada LINE, 6.000 pada TikTok, 7.000 pada Viber, 65.536 pada WhatsApp Web; tidak ada batasan pada email, widget obrolan, dan saluran kustom) dikirim sebagai beberapa pesan secara berurutan, dipisah pada jeda paragraf atau kalimat. Respons kemudian membawa messageIds untuk setiap bagian dan autoSplit: true. |
contact_id |
Tidak | ID kontak yang sudah ada. Jika diatur, bidang identitas di bawah tidak diperlukan. |
channel |
Tidak | Saluran untuk mengirim. Wajib jika contact_id tidak diberikan. Salah satu dari 14 saluran yang dapat mengirim keluar: whatsapp, whatsapp_web, sms, instagram, instagram_private, messenger, telegram, chat-widget, custom, email, line, imessage, linkedin, viber. |
phone_number |
Tidak | Nomor telepon kontak dalam format internasional. Digunakan dengan whatsapp, whatsapp_web, dan sms. |
instagram_id |
Tidak | ID pengguna Instagram kontak. Digunakan dengan instagram. |
messenger_id |
Tidak | ID pengguna Messenger kontak. Digunakan dengan messenger. |
telegram_user_id |
Tidak | ID pengguna Telegram kontak. Digunakan dengan telegram. |
media_url |
Tidak | URL file media untuk dilampirkan. |
media_content_type |
Tidak | Tipe MIME dari media yang dilampirkan, contohnya image/jpeg. |
Saluran mana yang dapat diselesaikan berdasarkan identitas. Hanya enam dari 14 saluran yang menerima bidang identitas sebagai pengganti contact_id: whatsapp, whatsapp_web dan sms dicari berdasarkan phone_number, instagram berdasarkan instagram_id, messenger berdasarkan messenger_id, dan telegram berdasarkan telegram_user_id. Delapan saluran lainnya — instagram_private, chat-widget, custom, email, line, imessage, linkedin dan viber — tidak memiliki identitas publik untuk dicari, sehingga pengiriman pada saluran tersebut memerlukan contact_id; mengirim channel saja akan mengembalikan 400 yang memberi tahu Anda bahwa contact_id diperlukan.
cURL (menggunakan formulir kueri ?apiKey=)
curl -X POST "https://api.youraiconnector.com/v1/contacts/send?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"channel": "whatsapp",
"phone_number": "+31612345678",
"body": "Hi! Your appointment is confirmed."
}'
JavaScript
const res = await fetch("https://api.youraiconnector.com/v1/contacts/send", {
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
channel: "whatsapp",
phone_number: "+31612345678",
body: "Hi! Your appointment is confirmed.",
}),
});
const data = await res.json();
console.log(data.message_id, data.channel);
Python
import requests
res = requests.post(
"https://api.youraiconnector.com/v1/contacts/send",
headers={
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"channel": "whatsapp",
"phone_number": "+31612345678",
"body": "Hi! Your appointment is confirmed.",
},
)
data = res.json()
print(data["message_id"], data["channel"])
Respons (201 Created):
{
"success": true,
"message_id": "aB3dE5fG7hI9jK1lM2nO",
"contact_id": "contact123",
"channel": "whatsapp"
}
Mengapa pesan mungkin ditolak: Kontak dengan mode jangan ganggu atau mode pribadi aktif tidak dapat menerima pesan keluar — permintaan akan gagal dengan
422. Jika tidak ada kontak yang cocok dengan ID atau identitas yang Anda berikan, Anda akan mendapatkan404.
Mengirim di WhatsApp Web: variasi dan perlindungan burst
Dua hal berlaku untuk body saat kontak berada di WhatsApp Web.
Kurung kurawal spintax diperluas per pengiriman. body dari {Hi|Hello|Hey} there, quick question akan keluar sebagai salah satu dari tiga salam, yang dipilih untuk pengiriman tersebut — kurung kurawal tidak akan pernah sampai ke kontak. Gunakan ini untuk memberikan pesan pembuka yang berbeda kepada setiap kontak dari kode integrasi yang sama. Teks tanpa kurung kurawal dikirim persis seperti yang tertulis.
Lonjakan pesan pembuka yang identik akan ditolak. Jika sepuluh pesan pembuka yang hampir identik keluar dari satu nomor WhatsApp Web dalam satu jam, kepada kontak yang belum pernah menulis kepada Anda, pesan selanjutnya tidak akan dikirim: pengiriman diterima seperti biasa (Anda tetap mendapatkan messageId), dan pesan tersebut kemudian dibiarkan dengan status: "failed" dan error_code: "opener_burst", dengan alasan yang dapat dibaca pelanggan di atasnya. Mencoba ulang teks yang sama tidak akan membantu — ubah teksnya, tunggu satu jam, lalu kirim lagi. Balasan di dalam percakapan yang sudah ada tidak akan pernah terpengaruh. Alasannya ada di Pembuka identik menyebabkan nomor dibatasi.
Kirim langsung ke nomor WhatsApp Web
POST /whatsapp-web/send
Kirim ke nomor telepon di WhatsApp Web tanpa perlu mencari kontak terlebih dahulu. Jika nomor tersebut belum menjadi kontak, kontak akan dibuat dalam panggilan yang sama, dengan AI dalam posisi nonaktif, sehingga pesan terbaca seperti pesan yang Anda kirim secara manual dan tidak ada asisten yang mengambil alih percakapan setelahnya. Kontak yang sudah ada akan digunakan kembali sebagaimana adanya.
| Bidang | Wajib | Deskripsi |
|---|---|---|
phoneNumber |
Ya | Nomor yang akan dikirimi pesan, dalam format internasional (+31612345678). |
message |
Tidak | Teks yang akan dikirim. Salah satu dari message atau mediaUrl harus ada. |
mediaUrl |
Tidak | URL publik dari file yang akan dikirim. Salah satu dari message atau mediaUrl harus ada. |
mediaContentType |
Tidak | Tipe MIME dari file tersebut, contohnya image/jpeg. Ditentukan dari URL jika Anda mengosongkannya. |
sendAsVoiceNote |
Tidak | true mengirim file audio sebagai pesan suara, bukan sebagai lampiran. |
fromPhoneNumber |
Tidak | Nomor WhatsApp Web Anda yang terhubung yang akan digunakan untuk mengirim, dalam format internasional. Default-nya adalah nomor yang sudah dimiliki kontak tersebut. |
campaignId |
Tidak | Gunakan jam aktif dari Agen ini alih-alih default akun. Harus merupakan Agen di akun yang sama. |
ignoreActiveHours |
Tidak | true mengirim pesan secara langsung, terlepas dari jam aktif yang ditentukan. |
sub_account_id |
Tidak | Untuk agensi: kirim atas nama salah satu akun klien Anda. |
curl -X POST "https://api.youraiconnector.com/v1/whatsapp-web/send?apiKey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phoneNumber": "+31612345678",
"message": "Hi Alex, your quote is ready."
}'
Panggilan yang berhasil akan menjawab 202:
{ "success": true, "queued": true, "contactId": "abc123" }
202 berarti diterima, belum terkirim. Di luar jam aktif, pengiriman akan ditahan dan dikirim pada slot waktu yang diizinkan berikutnya, kecuali jika Anda menyertakan ignoreActiveHours. Baca status pesan tersebut dengan Mencantumkan pesan kontak menggunakan contactId yang Anda dapatkan di sini.
Jika pesan tidak terkirim:
| Status | Kode | Apa yang terjadi |
|---|---|---|
400 |
INVALID_PHONE_FORMAT |
Nomor tidak dalam format internasional, atau phoneNumber tidak ada, atau baik message maupun mediaUrl tidak ada. |
400 |
CONTACT_DND |
Kontak tersebut dalam mode Jangan Ganggu, sehingga tidak ada pesan keluar yang dikirim ke mereka. |
400 |
CONTACT_PRIVATE |
Kontak tersebut ditandai sebagai pribadi. |
404 |
CAMPAIGN_NOT_FOUND |
Tidak ada Agen yang cocok dengan campaignId yang Anda masukkan. |
403 |
CAMPAIGN_FORBIDDEN |
Agen tersebut milik akun lain. |
402 |
Akun tidak memiliki kredit tersisa, atau tidak ada nomor WhatsApp Web yang terhubung. |
Panggilan kedua untuk kontak yang sama saat satu pengiriman tertahan masih menunggu akan menjawab 409, sehingga antrean tidak akan pernah menumpuk di belakang satu orang.
Mencatat catatan ke dalam percakapan
POST /contacts/notes
Menambahkan baris ke percakapan kontak tanpa mengirimnya. Gunakan ini untuk konteks yang harus diketahui oleh tim Anda dan AI, tetapi tidak boleh diterima oleh kontak: ringkasan panggilan telepon yang baru saja dilakukan agen suara Anda, komentar dari CRM Anda, atau catatan dari rekan kerja. Fitur ini berfungsi di semua saluran (WhatsApp, SMS, Instagram, Messenger, Telegram, widget obrolan, saluran kustom, dan sebagainya).
Apa yang terjadi pada sebuah catatan:
- Catatan akan muncul di obrolan dalam kotak masuk sebagai kartu Catatan berwarna kuning, beserta penulisnya jika Anda mencantumkannya.
- AI akan membacanya sebagai bagian dari riwayat percakapan, ditandai sebagai catatan internal, sehingga balasan berikutnya akan mempertimbangkannya.
- Catatan tidak akan pernah dikirim ke kontak, tidak memakan kredit pesan, dan tidak memicu apa pun: tidak ada balasan AI, tidak ada otomatisasi, tidak ada webhook, tidak ada notifikasi, tidak ada lencana belum dibaca. Catatan tidak menjeda AI dan tidak dihitung sebagai balasan dari tim Anda.
Temukan kontak dengan cara yang sama seperti Kirim berdasarkan identitas kontak: baik ID-nya, atau channel ditambah pengenal yang cocok. Catatan hanya dikirim ke kontak yang sudah ada; jika tidak ada yang cocok, maka akan menjadi 404.
| Bidang | Wajib | Deskripsi |
|---|---|---|
contact_id |
Salah satu dari keduanya | ID kontak. |
channel + identifier |
Salah satu dari keduanya | channel ditambah phone_number (WhatsApp, WhatsApp Web, SMS), instagram_id, messenger_id atau telegram_user_id, seperti dalam Kirim berdasarkan identitas kontak. |
body |
Ya | Teks catatan, hingga 4.000 karakter. Pemisah baris dipertahankan. |
author |
Tidak | Siapa atau apa yang menulisnya, hingga 80 karakter, contohnya Voice agent atau Sarah (sales). Ditampilkan pada kartu dan kepada AI. |
timestamp |
Tidak | Kapan itu terjadi, dalam milidetik epoch. Default-nya adalah sekarang. Gunakan waktu berakhir panggilan agar catatan berada di tempat yang tepat dalam utas. Tidak boleh lebih dari 5 menit di masa depan; waktu yang lebih lambat akan ditolak dengan 400. |
external_id |
Tidak | ID Anda sendiri untuk catatan ini, hingga 200 karakter, contohnya ID panggilan. Mengirim external_id yang sama untuk kontak yang sama lagi tidak akan menambahkan catatan kedua; respons kemudian akan membawa duplicate: true. Gunakan ini agar webhook yang dicoba ulang tidak mencatat panggilan yang sama dua kali. |
cURL
curl -X POST "https://api.youraiconnector.com/v1/contacts/notes" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"channel": "whatsapp",
"phone_number": "+31612345678",
"author": "Voice agent",
"body": "Voice call, 3:12. Asked about knee surgery waiting times, prefers a call back on Tuesday morning.",
"external_id": "call_8f2k1"
}'
Respons (201, atau 200 dengan duplicate: true jika external_id sudah dicatat)
{
"success": true,
"messageId": "note_4c1f0e...",
"contactId": "contact123"
}
Catatan muncul di Daftar pesan kontak dengan type: "note".
Buat draf balasan dengan AI
POST /contacts/{contactId}/draft-reply
Meminta agen AI yang menangani percakapan untuk menulis balasan berikutnya, dan memberikan teksnya kembali kepada Anda. Tidak ada yang dikirim. Ini adalah draf yang sama dengan yang ditulis oleh tombol Buat Balasan di kotak masuk: agen menggunakan pengaturannya, basis pengetahuannya, dan percakapan sejauh ini, lalu menjawab dalam bahasa kontak tersebut. Gunakan ini untuk menempatkan manusia (atau aplikasi Anda sendiri) di antara AI dan kontak: ambil drafnya, tampilkan untuk disetujui, lalu kirim dengan Kirim berdasarkan ID kontak, baik yang sudah diubah maupun apa adanya.
- Draf ditulis oleh agen yang ditugaskan ke kontak tersebut. Kontak yang belum memiliki agen akan mendapatkan agen yang akan menjawab pesan berikutnya.
- Saat membuat draf, agen tidak menjalankan alat atau fungsi apa pun, sehingga tidak ada pemesanan, penandaan, pengalihan, atau tindakan lain yang terjadi.
- Tidak ada yang disimpan dalam percakapan, dan kontak tidak melihat apa pun.
- Draf memakan kredit yang sama dengan satu balasan AI dari agen tersebut dalam percakapan ini, dan tidak memakan biaya apa pun saat kunci AI Anda sendiri terhubung.
- Percakapan harus memiliki setidaknya satu pesan.
Semua kolom isi bersifat opsional; isi yang kosong (atau tanpa isi) akan membuat draf balasan berikutnya.
| Bidang | Wajib | Deskripsi |
|---|---|---|
instruction |
Tidak | Arahan satu kali untuk draf ini, hingga 2.000 karakter, sama seperti menekan lama Buat Balasan di kotak masuk. Misalnya Offer Tuesday at 3pm atau Ask for their email address. |
campaign_id |
Tidak | Buat draf di bawah kampanye ini alih-alih agen kontak tersebut. |
purpose |
Tidak | chat_reply (default) menulis pesan kepada kontak. faq_answer menulis jawaban singkat untuk pertanyaan kontak yang berfungsi sendiri, untuk FAQ basis pengetahuan. |
cURL
curl -X POST "https://api.youraiconnector.com/v1/contacts/contact123/draft-reply" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "instruction": "Offer Tuesday at 3pm for the consultation" }'
Respons (200)
{
"success": true,
"contact_id": "contact123",
"draft": "Hi Sara, Tuesday at 3pm works for the consultation. Shall I put you down for it?"
}
400 berarti percakapan belum memiliki pesan, kredit Anda habis, atau kontak tidak memiliki agen atau kampanye untuk membuat draf (error menjelaskan yang mana). 404 berarti kontak tidak ada, atau kunci anggota tim terbatas pada kontak yang tidak dapat dilihatnya. Kunci atau anggota tim memerlukan izin untuk mengedit pesan.
Menggunakan klien AI melalui MCP? Tindakan yang sama tersedia sebagai alat
generate_reply_draft.
Mencantumkan pesan kontak
GET /contacts/{contactId}/messages
Mengembalikan pesan kontak, yang terbaru terlebih dahulu, dengan penomoran halaman berbasis kursor.
| Parameter kueri | Wajib | Deskripsi |
|---|---|---|
limit |
Tidak | Ukuran halaman. Default 50, maksimum 100. |
cursor |
Tidak | Nilai next_cursor dari respons sebelumnya. Mengembalikan pesan yang lebih lama dari kursor. |
filter |
Tidak | Filter berdasarkan tipe konten: all (default), text, media, atau tool_use. |
direction |
Tidak | Filter berdasarkan arah: all (default), inbound (diterima dari kontak), atau outbound (dikirim oleh Anda). |
Catatan tentang pemfilteran dan penomoran halaman: Filter
filterdandirectionditerapkan ke setiap halaman setelah dibaca, sehingga halaman yang difilter dapat berisi lebih sedikit item daripadalimit.next_cursortetap berlanjut melalui percakapan penuh, jadi terus lakukan penomoran halaman hingganext_cursoradalahnull.
cURL
curl "https://api.youraiconnector.com/v1/contacts/contact123/messages?limit=50&direction=inbound" \
-H "X-API-Key: YOUR_API_KEY"
JavaScript
const params = new URLSearchParams({ limit: "50", direction: "inbound" });
const res = await fetch(
`https://api.youraiconnector.com/v1/contacts/contact123/messages?${params}`,
{ headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
console.log(data.messages, data.next_cursor);
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/contacts/contact123/messages",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"limit": 50, "direction": "inbound"},
)
data = res.json()
print(data["messages"], data["next_cursor"])
Respons (200 OK):
{
"success": true,
"contact_id": "contact123",
"messages": [
{
"id": "aB3dE5fG7hI9jK1lM2nO",
"body": "Hi! Thanks for reaching out.",
"direction": "inbound",
"channel": "whatsapp",
"status": "delivered",
"type": null,
"timestamp": "2026-06-01T10:00:00.000Z",
"media_url": null,
"media_content_type": null,
"bot_reply": false
}
],
"next_cursor": "cD4eF6gH8iJ0kL2mN3oP"
}
Bidang pesan
| Bidang | Deskripsi |
|---|---|
id |
ID unik pesan. |
body |
Konten teks pesan. Untuk pesan dengan lampiran, body dimulai dengan catatan dalam kurung tentang apa yang diterima, diikuti oleh keterangan apa pun, misalnya [THE CONTACT UPLOADED AN IMAGE] Here is my CV atau [THE CONTACT UPLOADED A VOICE NOTE] - [TRANSCRIPTION: ...]. Catatan suara dan video menyertakan transkripsi. |
direction |
inbound (diterima dari kontak) atau outbound (dikirim oleh akun Anda). |
channel |
Saluran tempat pesan dikirim atau diterima (misalnya whatsapp, sms, instagram). |
status |
Status pengiriman saat ini, misalnya Created, sent, delivered, read, failed. |
type |
Jenis pesan. Pesan teks biasa memiliki jenis null; aktivitas alat asisten otomatis ditandai tool_use. |
timestamp |
Waktu ISO 8601 saat pesan dibuat. |
media_url |
URL file media yang dilampirkan, jika ada. Tautan ini berhenti berfungsi 7 hari setelah pesan diterima, di semua saluran (WhatsApp Business API, WhatsApp Web, Instagram, Messenger, Telegram, widget obrolan, dan lainnya). Dapatkan yang baru dengan Unduh lampiran pesan. |
media_content_type |
Jenis MIME dari media yang dilampirkan, jika ada. |
bot_reply |
true jika pesan dibuat oleh asisten AI. |
score |
Penilaian Anda terhadap pesan: 1 jempol ke atas, -1 jempol ke bawah, 0 jika belum dinilai. Lihat Nilai atau beri bintang pada pesan. |
is_important |
true jika pesan telah diberi bintang. |
is_deleted |
true jika pesan telah dihapus. Pesan yang dihapus tetap ada dalam daftar tetapi body dan media_url-nya kosong. |
reactions |
Reaksi emoji pada pesan, dari kedua belah pihak. Selalu berupa array — kosong jika tidak ada. Setiap entri memiliki emoji, from_phone_number, from_me (true jika reaksi tersebut adalah milik Anda) dan reacted_at. |
faq_ids_used |
ID FAQ Basis Pengetahuan yang dimiliki AI saat menulis balasan ini: yang dipilih untuk pesan terbaru ditambah yang disimpan dari percakapan sebelumnya. Daftar yang sama ada pada setiap pesan balasan yang dikirim dalam beberapa bagian. Selalu berupa array, kosong untuk pesan masuk, pesan yang dikirim oleh orang, tindak lanjut otomatis, dan balasan AI yang dikirim sebelum 25 September 2026. |
faqs_used |
FAQ yang sama dengan pertanyaannya: setiap entri memiliki id dan question. question adalah null jika FAQ telah dihapus sejak saat itu. |
Unduh lampiran pesan
POST /chat-exports/media/download-url
Memberikan Anda tautan unduhan baru untuk file yang dilampirkan pada pesan: gambar, pesan suara, video, atau dokumen. Tautan ini berlaku selama 1 jam. Gunakan fitur ini saat Anda ingin menyimpan lampiran di tempat lain (misalnya, mengarsipkan CV atau pesan suara yang dikirim kontak), atau saat media_url pada pesan atau Webhook Pesan Baru tidak lagi dapat dibuka.
Untuk menemukan pesan dengan lampiran, buat daftar pesan kontak dengan filter=media. id setiap pesan dan ID kontak membentuk messagePath.
| Bidang isi | Wajib | Deskripsi |
|---|---|---|
messagePath |
Ya | Pesan mana, dalam bentuk contacts/{contactId}/messages/{messageId}. |
cURL
curl -X POST "https://api.youraiconnector.com/v1/chat-exports/media/download-url" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"messagePath": "contacts/contact123/messages/aB3dE5fG7hI9jK1lM2nO"}'
JavaScript
const res = await fetch("https://api.youraiconnector.com/v1/chat-exports/media/download-url", {
method: "POST",
headers: { "X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json" },
body: JSON.stringify({ messagePath: "contacts/contact123/messages/aB3dE5fG7hI9jK1lM2nO" }),
});
const { data } = await res.json();
console.log(data.url); // download the file within the hour
Python
import requests
res = requests.post(
"https://api.youraiconnector.com/v1/chat-exports/media/download-url",
headers={"X-API-Key": "YOUR_API_KEY"},
json={"messagePath": "contacts/contact123/messages/aB3dE5fG7hI9jK1lM2nO"},
)
file_url = res.json()["data"]["url"]
Respons (200 OK):
{
"success": true,
"data": {
"url": "https://storage.googleapis.com/...",
"expiresInMs": 3600000
}
}
| Bidang | Deskripsi |
|---|---|
data.url |
Tautan unduhan. Ambil file langsung dari tautan tersebut, tidak perlu kunci API. |
data.expiresInMs |
Berapa lama tautan berfungsi, dalam milidetik (3600000 = 1 jam). Panggil endpoint lagi untuk mendapatkan tautan baru. |
| Status | Kapan |
|---|---|
400 |
messagePath hilang atau tidak dalam bentuk contacts/{contactId}/messages/{messageId}, atau pesan tidak memiliki lampiran yang dapat diunduh dengan cara ini. Beberapa lampiran lama disimpan di penyedia saluran dan tidak dapat diterbitkan ulang, dan reel atau postingan Instagram yang dibagikan merupakan tautan ke Instagram, bukan file. |
403 |
Kontak tersebut bukan milik akun Anda. |
404 |
Tidak ada pesan dengan ID tersebut pada kontak itu. |
Menggunakan klien AI melalui MCP? Tindakan yang sama tersedia sebagai alat
get_chat_media_download_url.
Daftar sesi obrolan
Sesi obrolan adalah satu jendela percakapan dengan kontak. Sesi ini terbuka pada pesan masuk pertama saat tidak ada sesi yang terbuka, dan tertutup secara otomatis 48 jam setelah pesan masuk terakhir dari kontak (setiap pesan masuk baru akan memperpanjang waktu penutupan selama 48 jam lagi). AI yang mengakhiri obrolan tidak menutup sesi; AI hanya memicu webhook Chat Concluded. Sesi adalah cara Anda membagi riwayat yang panjang menjadi percakapan yang dapat dibaca, alih-alih satu daftar yang tidak ada habisnya.
Sesi terbaru di semua kontak
GET /chat-sessions/recent
Mengembalikan sesi yang dimulai dalam X jam terakhir, yang terbaru terlebih dahulu, di seluruh kontak pada akun tersebut.
| Parameter kueri | Wajib | Deskripsi |
|---|---|---|
hours |
Ya | Berapa jam untuk melihat ke belakang. Harus berupa bilangan bulat positif. |
status |
Tidak | Hanya kembalikan sesi dengan status ini: ChatSessionOpened atau ChatSessionClosed. |
limit |
Tidak | Jumlah maksimum sesi yang akan dikembalikan. Default 100, maksimum 100. |
includeMessages |
Tidak | true menambahkan array messages ke setiap sesi. Nonaktif secara default karena membuat respons menjadi jauh lebih besar. |
cURL
curl "https://api.youraiconnector.com/v1/chat-sessions/recent?hours=24&status=ChatSessionClosed" \
-H "X-API-Key: YOUR_API_KEY"
JavaScript
const params = new URLSearchParams({ hours: "24", status: "ChatSessionClosed" });
const res = await fetch(`https://api.youraiconnector.com/v1/chat-sessions/recent?${params}`, {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
console.log(data.data.total_sessions, data.data.sessions);
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/chat-sessions/recent",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"hours": 24, "status": "ChatSessionClosed"},
)
data = res.json()["data"]
print(data["total_sessions"], data["sessions"])
Respons (200 OK):
{
"success": true,
"data": {
"hours_ago": 24,
"total_sessions": 2,
"sessions": [
{
"session_id": "session456",
"contact_id": "contact123",
"contact_name": "Jane Doe",
"contact_phone": "+31612345678",
"contact_email": "jane@example.com",
"start_date_time": "2026-06-01T09:55:00.000Z",
"end_date_time": "2026-06-01T10:20:00.000Z",
"status": "ChatSessionClosed",
"tag": "Booking enquiry"
}
]
}
}
Semua sesi untuk satu kontak
GET /chat-sessions/{contactId}
Mengembalikan setiap sesi obrolan untuk satu kontak. Parameter status, limit, dan includeMessages sama seperti di atas — hours tidak berlaku di sini.
cURL
curl "https://api.youraiconnector.com/v1/chat-sessions/contact123?limit=20" \
-H "X-API-Key: YOUR_API_KEY"
Respons (200 OK):
{
"success": true,
"data": {
"contact_id": "contact123",
"contact_name": "Jane Doe",
"total_sessions": 2,
"sessions": [
{
"id": "session456",
"start_date_time": "2026-06-01T09:55:00.000Z",
"end_date_time": "2026-06-01T10:20:00.000Z",
"status": "ChatSessionClosed",
"tag": "Booking enquiry"
}
]
}
}
Nama bidang ID sesi berbeda di antara kedua endpoint. Daftar sesi terbaru menyebutnya
session_id(ini juga memuat detail kontak, karena sesi berasal dari banyak kontak); daftar per-kontak menyebutnyaid. Nilai mana pun adalah yang Anda berikan sebagai{sessionId}saat mengambil utas lengkap di bawah.
Saat includeMessages=true, setiap sesi mendapatkan array messages yang entri-entrinya memuat id, body, direction, timestamp, type, channel, dan status.
Mengambil utas sesi obrolan
GET /contacts/{contactId}/chat-sessions/{sessionId}/messages
Sesi obrolan mengelompokkan pesan kontak ke dalam satu jendela percakapan. Titik akhir ini mengembalikan utas lengkap dari satu sesi, dari yang terlama, beserta metadata sesi tersebut. Anda dapat menemukan ID sesi untuk kontak melalui titik akhir sesi obrolan.
cURL
curl "https://api.youraiconnector.com/v1/contacts/contact123/chat-sessions/session456/messages" \
-H "X-API-Key: YOUR_API_KEY"
JavaScript
const res = await fetch(
"https://api.youraiconnector.com/v1/contacts/contact123/chat-sessions/session456/messages",
{ headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
console.log(data.session, data.messages);
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/contacts/contact123/chat-sessions/session456/messages",
headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
print(data["session"], data["messages"])
Respons (200 OK):
{
"success": true,
"contact_id": "contact123",
"session": {
"id": "session456",
"status": "ChatSessionClosed",
"start_date_time": "2026-06-01T09:55:00.000Z",
"end_date_time": "2026-06-01T10:20:00.000Z",
"tag": "Booking enquiry"
},
"messages": [
{
"id": "aB3dE5fG7hI9jK1lM2nO",
"body": "Hi! Thanks for reaching out.",
"direction": "inbound",
"channel": "whatsapp",
"status": "delivered",
"type": null,
"timestamp": "2026-06-01T09:55:00.000Z",
"media_url": null,
"media_content_type": null,
"bot_reply": false
}
]
}
Objek session melaporkan status (ChatSessionOpened saat aktif, ChatSessionClosed setelah berakhir), start_date_time, end_date_time, dan tag yang dapat dibaca manusia. Larik messages menggunakan bidang pesan yang sama dengan titik akhir daftar.
Edit, hapus, dan bereaksi terhadap pesan
Endpoint ini mengubah pesan setelah dikirim. Dua di antaranya menjangkau saluran kontak serta salinan Anda sendiri, jadi bacalah pengantar bagian sebelum menghubungkannya — apa yang mungkin dilakukan sepenuhnya bergantung pada saluran tempat percakapan berlangsung.
Apa yang diizinkan oleh setiap saluran
| Tindakan | Saluran yang dapat mengubah salinan kontak | Batas waktu |
|---|---|---|
| Edit pesan terkirim | Widget obrolan, WhatsApp Web (hanya pesan teks), Telegram, LinkedIn | Tidak ada pada widget obrolan, 15 menit pada WhatsApp Web, 48 jam pada Telegram, 60 menit pada LinkedIn |
| Hapus untuk semua orang | Widget obrolan, WhatsApp Web, Telegram, LinkedIn | 60 menit pada LinkedIn; yang lain tidak memiliki batas yang dipublikasikan |
| Bereaksi dengan emoji | WhatsApp Web, Telegram | Tidak ada |
Pada setiap saluran lain — WhatsApp Business API, SMS, Instagram, Messenger, email, LINE, saluran kustom — penghapusan tetap menghapus pesan dari kotak masuk Anda, tetapi kontak tetap menyimpan salinannya, dan pengeditan atau reaksi sama sekali tidak dimungkinkan.
Edit pesan
POST /contacts/{contactId}/messages/{messageId}/edit
Menulis ulang pesan yang sudah Anda kirim, baik di perangkat kontak maupun di salinan Anda.
| Bidang | Wajib | Deskripsi |
|---|---|---|
body |
Ya | Teks pesan baru. Tidak boleh kosong dan tidak boleh lebih panjang dari yang diizinkan saluran dalam satu pesan (batas per saluran sama dengan Kirim berdasarkan ID kontak; 4.096 jika pesan tidak memiliki saluran). |
Tidak seperti menghapus, tindakan ini gagal dengan notifikasi saat saluran menolak: Anda mendapatkan 409 dan salinan Anda dibiarkan persis seperti yang dimiliki kontak, karena menampilkan suntingan yang tidak pernah mereka terima akan membuat kedua sisi tidak sinkron. Bidang edit_reason memberi tahu Anda alasannya — jendela edit saluran telah ditutup, saluran terputus, pesan memiliki lampiran yang tidak dapat diedit oleh saluran (media_not_editable: di WhatsApp Web hanya pesan teks yang dapat diedit, bukan teks di bawah foto, video, atau file), atau ada hal lain yang salah.
cURL
curl -X POST "https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1/edit" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "body": "Sorry - I meant Thursday at 3pm." }'
JavaScript
const res = await fetch(
"https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1/edit",
{
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ body: "Sorry - I meant Thursday at 3pm." }),
}
);
const data = await res.json();
console.log(data.edited, data.edit_reason);
Python
import requests
res = requests.post(
"https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1/edit",
headers={
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
json={"body": "Sorry - I meant Thursday at 3pm."},
)
data = res.json()
print(data.get("edited"), data.get("edit_reason"))
Respons (200 OK):
{
"success": true,
"contact_id": "contact123",
"message_id": "msg_1",
"edited": true,
"edit_reason": "edit_dispatched"
}
Jika saluran tidak menerima editan tersebut, Anda akan mendapatkan 409 sebagai gantinya, dan tidak ada yang diubah:
{
"success": false,
"error": "The message could not be edited",
"edit_reason": "channel_disconnected"
}
Pesan yang sudah dihapus, saluran yang sama sekali tidak dapat mengedit, dan pesan yang terlalu lama untuk salurannya, semuanya mengembalikan 400 — permintaan tidak pernah mencapai saluran tersebut.
Hapus satu pesan
DELETE /contacts/{contactId}/messages/{messageId}
Menghapus pesan dari percakapan Anda dan, jika saluran mengizinkannya, menarik kembali salinan kontak juga. Tidak ada isi permintaan.
Ini selalu menjawab 200 jika pesan tersebut ada, meskipun salinan kontak tidak dapat ditarik kembali — salinan Anda sudah hilang, jadi kesalahan akan menyesatkan. Baca ketiga bidang dalam respons untuk memberi tahu pengguna apa yang sebenarnya terjadi:
| Bidang | Deskripsi |
|---|---|
revoke_supported |
Apakah saluran ini dapat menarik kembali pesan atau tidak. |
revoked |
Apakah salinan di perangkat kontak telah dihapus. |
revoke_reason |
Mengapa pesan tidak dihapus, saat revoked adalah false — contohnya revoke_window_closed atau already_deleted. |
cURL
curl -X DELETE "https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1" \
-H "X-API-Key: YOUR_API_KEY"
JavaScript
const res = await fetch(
"https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1",
{ method: "DELETE", headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
console.log(data.revoked, data.revoke_reason);
Python
import requests
res = requests.delete(
"https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1",
headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
print(data["revoked"], data["revoke_reason"])
Respons (200 OK):
{
"success": true,
"contact_id": "contact123",
"message_id": "msg_1",
"revoke_supported": true,
"revoked": true,
"revoke_reason": "revoke_dispatched"
}
Pesan yang dihapus tidak akan hilang dari riwayat percakapan. Pesan tersebut tetap ada di
GET /contacts/{contactId}/messagesdenganis_deleted: truesertabodydanmedia_urlyang kosong.
Menghapus beberapa pesan sekaligus
POST /contacts/{contactId}/messages/bulk-delete
Menghapus sekumpulan pesan hanya dari sisi Anda. Isi dan lampiran akan dikosongkan, namun tidak ada yang ditarik kembali di perangkat kontak — untuk menarik kembali pesan, hapuslah satu per satu menggunakan endpoint pesan tunggal di atas.
| Bidang | Wajib | Deskripsi |
|---|---|---|
message_ids |
Ya | Array ID pesan yang tidak kosong, maksimal 500 per permintaan. messageIds diterima sebagai alias. |
cURL
curl -X POST "https://api.youraiconnector.com/v1/contacts/contact123/messages/bulk-delete" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "message_ids": ["msg_1", "msg_2"] }'
JavaScript
const res = await fetch(
"https://api.youraiconnector.com/v1/contacts/contact123/messages/bulk-delete",
{
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ message_ids: ["msg_1", "msg_2"] }),
}
);
console.log((await res.json()).deleted);
Python
import requests
res = requests.post(
"https://api.youraiconnector.com/v1/contacts/contact123/messages/bulk-delete",
headers={
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
json={"message_ids": ["msg_1", "msg_2"]},
)
print(res.json()["deleted"])
Respons (200 OK):
{
"success": true,
"contact_id": "contact123",
"deleted": 2
}
Memberikan reaksi pada pesan
POST /contacts/{contactId}/messages/{messageId}/react
Memberikan reaksi emoji Anda sendiri pada sebuah pesan, atau menariknya kembali dengan mengirimkan string kosong. Reaksi milik kontak tidak akan pernah diubah.
| Bidang | Wajib | Deskripsi |
|---|---|---|
emoji |
Ya | Emoji untuk memberikan reaksi, atau "" untuk menghapus reaksi Anda. Harus berupa string tunggal tanpa spasi, maksimal 16 karakter. |
Seperti halnya pengeditan, tindakan ini akan gagal alih-alih menampilkan reaksi yang tidak pernah diterima oleh kontak, dan kegagalan tersebut memberi tahu Anda apakah percobaan ulang layak dilakukan:
422— pesan tidak akan pernah bisa dikirimkan dalam percakapan ini: saluran tidak mendukung reaksi, pesan tidak memiliki ID sisi saluran, atau emoji berada di luar rangkaian yang diizinkan oleh saluran tersebut.409— saluran tidak dapat dijangkau untuk sementara. Percobaan ulang mungkin berhasil.
cURL
curl -X POST "https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1/react" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "emoji": "👍" }'
JavaScript
const res = await fetch(
"https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1/react",
{
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ emoji: "👍" }),
}
);
const data = await res.json();
console.log(data.reactions);
Python
import requests
res = requests.post(
"https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1/react",
headers={
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
json={"emoji": "👍"},
)
print(res.json()["reactions"])
Respons (200 OK):
{
"success": true,
"contact_id": "contact123",
"message_id": "msg_1",
"reaction_supported": true,
"reaction_reason": "reaction_dispatched",
"reactions": [
{
"emoji": "👍",
"from_phone_number": "+31612345678",
"from_me": true,
"reacted_at": "2026-06-01T10:05:00.000Z"
}
]
}
Array reactions adalah rangkaian lengkap reaksi yang ada pada pesan saat ini, baik milik Anda maupun milik kontak. Pada 409 atau 422, array ini dikembalikan tanpa perubahan, sehingga klien yang melakukan rendering langsung darinya tidak akan pernah menampilkan reaksi yang tidak terkirim.
Memberi peringkat atau menandai pesan
PATCH /contacts/{contactId}/messages/{messageId}
Memberi peringkat jempol ke atas atau jempol ke bawah pada pesan dan/atau menandainya sebagai penting. Ini hanyalah pencatatan di sisi Anda saja — tidak ada yang dikirimkan ke kontak.
| Bidang | Wajib | Deskripsi |
|---|---|---|
score |
Tidak | 1 jempol ke atas, -1 jempol ke bawah, 0 menghapus peringkat. |
is_important |
Tidak | true memberi bintang pada pesan, false menghapus bintangnya. Harus berupa boolean asli, bukan string "true". |
Kirim setidaknya salah satu dari keduanya, atau Anda akan mendapatkan 400. Hanya apa yang Anda kirim yang akan ditulis, jadi memberi bintang pada pesan tidak akan pernah menghapus peringkatnya dan sebaliknya — dan respons hanya akan menggemakan kembali bidang yang Anda kirim.
cURL
curl -X PATCH "https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "score": 1, "is_important": true }'
JavaScript
await fetch("https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1", {
method: "PATCH",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ score: 1, is_important: true }),
});
Python
import requests
requests.patch(
"https://api.youraiconnector.com/v1/contacts/contact123/messages/msg_1",
headers={"X-API-Key": "YOUR_API_KEY"},
json={"score": 1, "is_important": True},
)
Respons (200 OK):
{
"success": true,
"contact_id": "contact123",
"message_id": "msg_1",
"score": 1,
"is_important": true
}
Menandai pesan sebagai telah dibaca
Anda dapat menghapus status belum dibaca baik untuk pesan tertentu maupun untuk keseluruhan percakapan.
Menandai pesan tertentu sebagai telah dibaca
POST /contacts/{contactId}/messages/mark-read
Teruskan ID pesan yang akan ditandai sebagai telah dibaca.
| Bidang | Wajib | Deskripsi |
|---|---|---|
message_ids |
Ya | Larik ID pesan yang tidak kosong (hingga 500 per permintaan). |
cURL
curl -X POST "https://api.youraiconnector.com/v1/contacts/contact123/messages/mark-read" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"message_ids": ["aB3dE5fG7hI9jK1lM2nO", "cD4eF6gH8iJ0kL2mN3oP"]
}'
JavaScript
const res = await fetch(
"https://api.youraiconnector.com/v1/contacts/contact123/messages/mark-read",
{
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
message_ids: ["aB3dE5fG7hI9jK1lM2nO", "cD4eF6gH8iJ0kL2mN3oP"],
}),
}
);
const data = await res.json();
console.log(data.marked_read);
Python
import requests
res = requests.post(
"https://api.youraiconnector.com/v1/contacts/contact123/messages/mark-read",
headers={
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
json={"message_ids": ["aB3dE5fG7hI9jK1lM2nO", "cD4eF6gH8iJ0kL2mN3oP"]},
)
print(res.json()["marked_read"])
Respons (200 OK):
{
"success": true,
"contact_id": "contact123",
"marked_read": 2
}
Menandai seluruh obrolan sebagai telah dibaca
POST /contacts/{contactId}/mark-read
Menghapus lencana belum dibaca untuk seluruh percakapan kontak di kotak masuk. Tidak diperlukan isi permintaan.
cURL
curl -X POST "https://api.youraiconnector.com/v1/contacts/contact123/mark-read" \
-H "X-API-Key: YOUR_API_KEY"
JavaScript
const res = await fetch(
"https://api.youraiconnector.com/v1/contacts/contact123/mark-read",
{ method: "POST", headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
console.log(data.success);
Python
import requests
res = requests.post(
"https://api.youraiconnector.com/v1/contacts/contact123/mark-read",
headers={"X-API-Key": "YOUR_API_KEY"},
)
print(res.json()["success"])
Respons (200 OK):
{
"success": true,
"contact_id": "contact123"
}
Tandai seluruh obrolan sebagai belum dibaca
POST /contacts/{contactId}/mark-unread
Menempatkan kembali lencana belum dibaca pada percakapan — berguna ketika seseorang di tim Anda membuka obrolan tetapi menyerahkannya kembali. Tidak diperlukan isi permintaan.
Ini adalah tanda khusus kotak masuk: ini tidak mengubah kapan percakapan terakhir dibaca, jadi tidak ada tanda terima telah dibaca yang dikirim ke kontak pada saluran yang mendukungnya.
cURL
curl -X POST "https://api.youraiconnector.com/v1/contacts/contact123/mark-unread" \
-H "X-API-Key: YOUR_API_KEY"
Respons (200 OK):
{
"success": true,
"contact_id": "contact123"
}
Ekspor percakapan
Ekspor memberikan Anda seluruh percakapan sebagai transkrip yang dapat dibaca, alih-alih menelusuri pesan halaman demi halaman. Setiap titik akhir ekspor menerima filter berupa all (default), text, media, atau tool_use, yang cocok dengan filter pada daftar pesan.
Ekspor obrolan satu kontak
GET /chat-exports/{contactId}
| Parameter kueri | Wajib | Deskripsi |
|---|---|---|
format |
Tidak | txt (default) mengembalikan tautan unduhan ke transkrip teks biasa. json mengembalikan pesan sebagai data terstruktur dalam respons. |
filter |
Tidak | all (default), text, media, atau tool_use. |
cURL
curl "https://api.youraiconnector.com/v1/chat-exports/contact123?format=json" \
-H "X-API-Key: YOUR_API_KEY"
Python
import requests
res = requests.get(
"https://api.youraiconnector.com/v1/chat-exports/contact123",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"format": "json"},
)
print(res.json()["data"]["messages"])
Respons dengan format=json (200 OK):
{
"success": true,
"data": {
"contact": {
"id": "contact123",
"name": "Jane Doe",
"phone": "+31612345678",
"email": "jane@example.com"
},
"messages": [
{
"body": "Hi! I have a question about my order.",
"direction": "inbound",
"timestamp": "2026-06-01T09:55:00.000Z",
"type": "text",
"media_url": null,
"media_content_type": null,
"name": null,
"args": null
}
]
}
}
Dengan format=txt (default), data justru merupakan tautan unduhan ke file transkrip yang dihasilkan:
{
"success": true,
"data": "https://storage.googleapis.com/.../chat-export-contact123-....txt"
}
Tautan unduhan hanya berlaku singkat. Ambil file segera setelah Anda mendapatkan tautan alih-alih menyimpannya — minta ekspor baru saat Anda membutuhkan transkrip lagi.
Ekspor setiap percakapan terbaru
GET /chat-exports/recent
Mengekspor percakapan dari semua kontak yang aktif dalam X jam terakhir, dalam satu panggilan.
| Parameter kueri | Wajib | Deskripsi |
|---|---|---|
hours |
Ya | Berapa jam aktivitas yang ingin dilihat ke belakang. Harus berupa bilangan bulat positif. |
format |
Tidak | json (default) mengembalikan satu entri per kontak. txt mengembalikan satu file teks yang dapat diunduh berisi setiap percakapan. |
limit |
Tidak | Jumlah maksimum kontak yang akan diekspor. Default 50, maksimum 100. |
filter |
Tidak | all (default), text, media atau tool_use. |
cURL
curl "https://api.youraiconnector.com/v1/chat-exports/recent?hours=24&limit=25" \
-H "X-API-Key: YOUR_API_KEY"
Respons (200 OK):
{
"success": true,
"data": {
"hours_ago": 24,
"total_contacts": 2,
"exports": [
{
"contactId": "contact123",
"contactName": "Jane Doe",
"phoneNumber": "+31612345678",
"email": "jane@example.com",
"messageCount": 12,
"chatExport": "Acme Export - Jane Doe\nPhone: +31612345678\n..."
}
]
}
}
Dengan format=txt, responsnya adalah file teks itu sendiri, dikirim sebagai unduhan alih-alih JSON.
Satu panggilan ini menarik riwayat lengkap dari setiap kontak yang cocok, jadi jaga agar
hoursdanlimittetap wajar pada akun yang sibuk.
Mengirim transkrip melalui email ke kontak
POST /chat-exports/{contactId}/email
Mengirimkan transkrip percakapan mereka sendiri kepada kontak melalui email — alur “kirimkan obrolan ini ke email saya”, yang dijalankan dari sistem Anda sendiri.
| Bidang | Wajib | Deskripsi |
|---|---|---|
recipient_email |
Tidak | Ke mana harus mengirimnya. Defaultnya adalah alamat email kontak yang tersimpan. |
via |
Tidak | auto (default) memilih rute terbaik, transactional mengirimnya sebagai email sistem, email_channel mengirimnya dari saluran email Anda yang terhubung. |
note |
Tidak | Baris singkat dari Anda yang ditampilkan di atas transkrip. Hingga 1000 karakter. |
cURL
curl -X POST "https://api.youraiconnector.com/v1/chat-exports/contact123/email" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "note": "Here is a copy of our chat, as promised." }'
Respons (200 OK):
{
"success": true,
"data": {
"via": "transactional",
"recipientEmail": "jane@example.com",
"messageCount": 42,
"omittedCount": 0
}
}
omittedCount memberi tahu Anda berapa banyak pesan terlama yang ditinggalkan agar email tetap memiliki panjang yang wajar. 200 berarti transkrip telah dibuat dan dimasukkan ke antrean untuk dikirim, bukan berarti pesan tersebut sudah sampai di kotak masuk.
Jeda atau lanjutkan AI untuk satu kontak
PUT /contacts/{contactId}
Atur is_bot_active ke false untuk menghentikan AI membalas satu kontak, dan kembali ke true untuk mengembalikan percakapan. Ini adalah tombol pengambilalihan yang Anda perlukan saat manusia masuk ke dalam percakapan: pesan keluar yang Anda kirim dengan API tetap terkirim saat bot dijeda.
cURL
curl -X PUT "https://api.youraiconnector.com/v1/contacts/contact123" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "is_bot_active": false }'
JavaScript
await fetch("https://api.youraiconnector.com/v1/contacts/contact123", {
method: "PUT",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ is_bot_active: false }),
});
Python
import requests
requests.put(
"https://api.youraiconnector.com/v1/contacts/contact123",
headers={"X-API-Key": "YOUR_API_KEY"},
json={"is_bot_active": False},
)
Respons
{
"success": true,
"contact_id": "contact123"
}
Menjeda sebagai bagian dari balasan
Jika manusia mengambil alih dengan mengirim balasan, Anda dapat menjeda bot dalam permintaan yang sama alih-alih melakukan panggilan kedua. POST /contacts/{contactId}/send-message menerima flag opsional berikut:
| Bidang | Deskripsi |
|---|---|
pauseBot |
true menjeda AI untuk kontak ini saat pesan dikirim. |
clearIncompleteReply |
true membuang balasan bot yang setengah jadi agar tidak dilanjutkan setelahnya. |
human_reply |
true menandai pesan sebagai balasan rekan tim dan membatalkan balasan yang telah diantrekan AI. Menjeda tetap memerlukan pauseBot. |
curl -X POST "https://api.youraiconnector.com/v1/contacts/contact123/send-message" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"body": "Hi, Sarah here - taking over from the assistant.",
"pauseBot": true,
"clearIncompleteReply": true,
"human_reply": true
}'
Respons mencakup "botPaused": true saat jeda diterapkan.
Menandai kontak sebagai pribadi dengan
POST /contacts/bulk-flagjuga menjeda bot untuk mereka. Lihat Kontak untuk daftar bidang lengkap.
Membangun kotak masuk Anda sendiri
Segala sesuatu yang dibutuhkan kotak masuk ada di halaman ini dan di Kontak:
| Apa yang Anda butuhkan | Endpoint |
|---|---|
| Mencantumkan percakapan | GET /contacts |
| Membaca percakapan | GET /contacts/{contactId}/messages |
| Mencantumkan sesi obrolan kontak | GET /chat-sessions/{contactId} |
| Melihat apa yang baru saja masuk | GET /chat-sessions/recent |
| Membaca satu sesi obrolan | GET /contacts/{contactId}/chat-sessions/{sessionId}/messages |
| Mengirim balasan manual | POST /contacts/{contactId}/send-message |
| Mengoreksi balasan yang baru saja Anda kirim | POST /contacts/{contactId}/messages/{messageId}/edit |
| Menghapus pesan | DELETE /contacts/{contactId}/messages/{messageId} |
| Menghapus beberapa pesan | POST /contacts/{contactId}/messages/bulk-delete |
| Bereaksi dengan emoji | POST /contacts/{contactId}/messages/{messageId}/react |
| Memberi peringkat atau membintangi pesan | PATCH /contacts/{contactId}/messages/{messageId} |
| Menandai sebagai telah dibaca | POST /contacts/{contactId}/mark-read |
| Mengembalikan obrolan ke tim | POST /contacts/{contactId}/mark-unread |
| Mengekspor transkrip | GET /chat-exports/{contactId} |
| Menjeda atau melanjutkan AI | PUT /contacts/{contactId} dengan is_bot_active |
Untuk pembaruan langsung, berlanggananlah ke acara New Message, Replies, Human Alerted, dan Chat Concluded dengan Webhook alih-alih melakukan polling pada API ini secara berkala.
Kesalahan API Pesan
Endpoint pesan mengembalikan amplop kesalahan standar:
{
"success": false,
"error": "Contact not found"
}
| Status | Kapan ini terjadi pada endpoint pesan |
|---|---|
400 |
Bidang wajib hilang atau parameter tidak valid (bad limit, hours, filter, direction, status, array message_ids kosong atau lebih dari 500, cursor tidak valid, edit body kosong atau terlalu panjang, score di luar -1/0/1, atau emoji dengan spasi atau lebih dari 16 karakter). Juga dikembalikan saat pesan tidak dapat diedit sama sekali — pesan telah dihapus, salurannya tidak memiliki fitur edit, atau sudah melewati jendela edit saluran tersebut. |
404 |
Kontak, sesi obrolan, atau salah satu ID pesan yang diberikan tidak ditemukan. |
409 |
Saluran tidak dapat menerima perubahan saat ini. Tidak ada yang ditulis: saat pengeditan, edit_reason menjelaskan alasannya; saat reaksi, saluran tidak dapat dijangkau untuk sementara dan mencoba lagi mungkin berhasil. |
422 |
Kontak tidak dapat menerima pesan keluar (jangan ganggu, pribadi, atau saluran yang tidak didukung), atau reaksi tidak pernah dapat dikirimkan pada percakapan ini (reaction_reason menjelaskan yang mana). |
Kode bersama yang dapat dikembalikan oleh setiap endpoint — 401, 403 (paket Anda tidak menyertakan akses API), 429 (batas kecepatan) dan 500 — tercantum beserta panduan percobaan ulang di Kesalahan & Penomoran Halaman.
Langkah berikutnya
- Webhook — dapatkan pembaruan status pengiriman yang dikirimkan kepada Anda alih-alih melakukan polling.
- Kontak — buat dan cari kontak yang Anda kirimi pesan.
- Janji Temu — pesan dan kelola janji temu untuk kontak Anda.