Ikhtisar API
Setiap endpoint REST RolChat mengikuti satu kontrak: base URL yang sama, amplop respons yang sama, paginasi yang sama, bentuk kesalahan yang sama. Pelajari sekali, dan setiap keluarga endpoint di referensi endpoint dapat dibaca dengan cara yang sama.
Base URL dan versi
Section titled “Base URL dan versi”https://api.rolchat.com/api/v1/Versi ada di path. Menambahkan field opsional, endpoint baru, atau parameter query baru dengan nilai default bukan perubahan yang merusak kompatibilitas dan tidak menaikkan versi. Perubahan yang merusak kompatibilitas dirilis sebagai v2, dan endpoint v1 yang dihentikan tetap berfungsi setidaknya enam bulan setelah diumumkan (lihat Penghentian).
Autentikasi
Section titled “Autentikasi”| Metode | Header | Digunakan untuk |
|---|---|---|
| JWT bearer | Authorization: Bearer <access_token> |
Sesi interaktif (aplikasi web, aplikasi seluler) |
| Kunci API | Authorization: Bearer rcp_<secret> |
Panggilan antarmesin, kunci API plugin |
| Tanda tangan HMAC | X-RolChat-Signature: sha256=… |
Webhook masuk dari sistem Anda, lihat Webhook |
| Tidak ada | - | Endpoint widget publik (/widget/…, /forms/…), dibatasi per situs dan origin |
Untuk integrasi, gunakan kunci API (token akses pribadi). Kunci dibuat di Pengaturan → Plugin → Kunci API RolChat, ditampilkan sekali, dan disimpan hanya sebagai hash. Kunci tidak pernah dapat melakukan lebih dari anggota yang membuatnya: scope-nya diperiksa terhadap izin anggota tersebut saat ini pada setiap panggilan. Lihat Autentikasi untuk masa berlaku JWT, header X-Account-Id, dan sesi multi-perusahaan.
Amplop respons
Section titled “Amplop respons”Satu resource:
{ "data": { "id": "cnt_01HK…", "email": "ada@example.com" }, "meta": { "request_id": "req_01HK…" }}Sebuah daftar:
{ "data": [ { … }, { … } ], "meta": { "request_id": "req_01HK…", "count": 50, "next_cursor": "cur_01HK…", "prev_cursor": "cur_01HK…", "has_more": true }}Respons tanpa body (204 No Content setelah penghapusan) tetap membawa header X-Request-Id.
Sebuah kesalahan:
{ "errors": [ { "code": "validation_failed", "message": "Email must be valid.", "field": "email", "details": { "received": "not-an-email" } } ], "meta": { "request_id": "req_01HK…" }}code adalah nilai snake_case yang dapat dibaca mesin dan menjadi dasar percabangan logika Anda; message berbahasa Inggris dan ditujukan untuk log. field dan details disertakan jika membantu dan tidak pernah berisi data pribadi. API tidak pernah menjawab 200 dengan array errors: jika ada kesalahan, statusnya 400 atau lebih tinggi. Daftar kode lengkap ada di halaman Kesalahan.
Paginasi
Section titled “Paginasi”Endpoint daftar yang dapat bertambah besar menggunakan paginasi kursor. Minta halaman pertama tanpa kursor, lalu kirim kembali next_cursor yang Anda terima apa adanya:
GET /api/v1/contacts?limit=50GET /api/v1/contacts?limit=50&cursor=eyJrIjoi…limitdefault-nya 50 dan maksimal 200; nilai yang lebih besar ditolak dengan400 validation_failed.- Kursor bersifat opak dan kedaluwarsa setelah 24 jam (
400 validation_faileddengancode: cursor_expired). - Hasil konsisten terhadap snapshot yang diambil pada halaman pertama: catatan yang dihapus di antara halaman menghilang, catatan baru hanya muncul saat Anda memulai lagi tanpa kursor.
- Header
Linkdenganrel="next"danrel="prev"juga dikirim untuk klien yang lebih menyukainya.
Idempotensi
Section titled “Idempotensi”Kirim header Idempotency-Key (UUID atau ULID, hingga 255 karakter) bersama POST, PATCH, atau DELETE apa pun:
- Permintaan pertama dengan sebuah kunci dijalankan, dan status serta body-nya disimpan selama 24 jam.
- Pengulangan dengan kunci yang sama dan body yang sama mengembalikan respons tersimpan tanpa menjalankan efek samping lagi.
- Pengulangan dengan kunci yang sama tetapi body berbeda ditolak dengan
409 idempotency_key_conflict.
Gunakan untuk setiap panggilan yang membuat sesuatu dengan efek samping: mengirim pesan, email, atau SMS, melakukan panggilan, apa pun yang ditagih. Permintaan GET selalu idempoten dan mengabaikan header ini.
Batas laju
Section titled “Batas laju”Batas dihitung per menit dan diberlakukan per akun, kunci API, atau pengguna (per alamat IP pada rute yang tidak memerlukan login). Batas atas default:
| Bucket | Batas default | Per menit |
|---|---|---|
| Permintaan tanpa login (per IP) | 60 | per IP |
| Pengguna yang login (dasbor) | 1 000 | per pengguna |
| Kunci API | 1 000 | per kunci |
| Endpoint widget publik | 60 per pengunjung, dan 600 per alamat jaringan | per menit |
Login (/auth/login) |
5 | per IP |
| Webhook masuk | 300 | per menit |
| Server MCP | 600 | per menit |
| Endpoint OAuth | 600 | per menit |
Batas ini adalah default platform dan dapat diubah oleh operator; paket Anda tidak melipatgandakannya, dan batas Enterprise disepakati dalam kontrak Anda. Endpoint yang dibatasi lajunya mengembalikan:
X-RateLimit-Limit: 1000X-RateLimit-Remaining: 543Saat Anda melampaui batas, responsnya 429 dengan code: rate_limited di array errors dan header Retry-After dalam detik. Tunggu selama itu sebelum panggilan berikutnya. Sepuluh kali login gagal mengunci akun selama 30 menit.
Ukuran dan batas waktu
Section titled “Ukuran dan batas waktu”| Kategori | Maks. body permintaan | Batas waktu server |
|---|---|---|
| Default | 1 MB | 30 dtk |
| Pesan dengan lampiran | 25 MB | 30 dtk |
| Impor CSV | 50 MB | mengembalikan 202 dan berjalan di latar belakang |
| Gambar basis pengetahuan | 10 MB | 30 dtk |
| Bulk API | 10 MB | 30 dtk |
| Pencarian | 1 MB | 10 dtk |
| Permintaan AI | 1 MB | 60 dtk |
| Endpoint widget | 100 KB | 30 dtk |
Body yang terlalu besar mendapat 413 payload_too_large. Layanan upstream yang kehabisan waktu menjawab 504 dengan code: upstream_timeout dan petunjuk retry_after jika percobaan ulang dapat membantu.
Tipe konten, tanggal, dan ID
Section titled “Tipe konten, tanggal, dan ID”- Permintaan dan respons menggunakan
application/json; charset=utf-8. Unggahan file menggunakanmultipart/form-data; ekspor CSV mengembalikantext/csv. UTF-8 yang tidak valid ditolak dengan400 validation_failed. - Stempel waktu menggunakan ISO-8601 dalam UTC dengan presisi milidetik:
2026-04-20T14:23:45.123Z. Offset ISO-8601 apa pun diterima sebagai input dan dinormalkan ke UTC. - Identifier berupa ULID atau UUID yang opak. Tidak ada ID numerik, dan alamat email atau nomor telepon tidak pernah muncul di URL.
Isolasi tenant dan izin
Section titled “Isolasi tenant dan izin”Setiap permintaan terautentikasi berjalan di dalam satu akun. Resource milik akun lain, atau milik situs yang tidak dicakup peran pemanggil, menjawab 404 not_found alih-alih 403, agar keberadaan catatan tidak pernah bocor. Token valid tanpa izin yang diperlukan (misalnya contacts.delete) menjawab 403 forbidden. Beberapa izin membawa akhiran cakupan (conversations.read:own, :team, :all) yang mempersempit apa yang dikembalikan sebuah daftar.
PATCH hanya menerima field yang dapat ditulis. id, account_id, created_at, updated_at, dan field status seperti resolved_at bersifat hanya baca; mengirim salah satunya mengembalikan 400 validation_failed dengan details.forbidden_fields. Perubahan status dilakukan melalui aksi khusus seperti POST /tickets/:id/resolve.
Setiap penulisan dicatat di log audit akun.
Header observabilitas
Section titled “Header observabilitas”Setiap respons membawa:
X-Request-Id: req_01HK…Catat X-Request-Id di log. Itulah hal pertama yang akan diminta tim dukungan.
Origin dasbor di browser adalah https://app.rolchat.com. Endpoint widget publik mengizinkan origin apa pun, atau hanya origin yang Anda verifikasi untuk sebuah situs. Panggilan server-ke-server dengan kunci API tidak tunduk pada CORS.
Penghentian
Section titled “Penghentian”- Perubahan diumumkan di log perubahan dan endpoint yang terdampak mulai mengirim
Deprecation: truedan headerSunsetberisi tanggal penghapusan. - Endpoint publik tetap berfungsi setidaknya enam bulan setelah pengumuman.
- Penghapusan hanya terjadi di versi mayor baru. Di dalam
v1, perubahan hanya bersifat penambahan.
Kesehatan
Section titled “Kesehatan”Setiap layanan menyediakan /healthz (liveness) dan /readyz (readiness).