API v1
Base URL: https://onix.sassly.ai/api/v1. Semua path di halaman ini relatif terhadap base URL. Body request berformat JSON
(Content-Type: application/json). Spesifikasi lengkap OpenAPI 3.1: /docs/openapi.yaml
— bisa diimpor ke Postman, Insomnia, atau generator SDK.
Autentikasi
| Aplikasi Onix (browser) | Integrasi (server-mu) | |
|---|---|---|
| Identitas | Cookie sesi setelah masuk dengan Google | Header Authorization: Bearer onx_live_… |
| Request yang mengubah data | Wajib header X-CSRF-Token milik sesi; aplikasi mengirimnya otomatis | Tanpa CSRF; key ber-scope write |
| Hak akses | Sesuai role dan akses channel pengguna | Seluruh workspace, dibatasi scope key |
| Paket | Semua paket | Pro dan Custom |
Membuat API key
- Buka Pengaturan → API (butuh akses Kelola API key; khusus Pro).
- Klik Buat key, beri nama (mis. "Integrasi CRM"), lalu pilih scope:
read(hanya membaca) atauwrite(membaca dan mengubah data). - Key berawalan
onx_live_dan hanya ditampilkan sekali. Simpan di secret manager; jangan taruh di kode frontend atau repositori. - Maksimal 10 key aktif per workspace. Request dengan key yang sudah dicabut dibalas
401.
export ONIX_API_KEY="onx_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
API key bertindak atas nama workspace dan tidak dibatasi role, jadi perlakukan seperti password. Endpoint pengelolaan (anggota, role, pengaturan, API key, tagihan) hanya bisa dari aplikasi. API tidak mendukung CORS: panggil dari server, bukan dari JavaScript di browser.
Format respons
Respons sukses selalu berbentuk {"data": …, "meta": {…}}; meta hanya ada bila relevan. Respons error selalu berbentuk:
{
"error": {
"code": "validation_error",
"message": "Nama workspace 2–120 karakter.",
"fields": {"name": "Nama workspace 2–120 karakter."}
}
}
codetetap dan aman dipakai di logika program;messageadalah teks untuk manusia yang mengikuti bahasa (headerX-Locale: en|id).fieldshanya ada pada error input, berisi pesan per kolom.- Waktu selalu UTC dalam ISO 8601, mis.
2026-10-08T02:30:00Z. Ubah ke zona waktumu sendiri saat menampilkan; aplikasi Onix memakai zona pribadi pengguna atau zona workspace. - Daftar berhalaman menerima
page(mulai 1) danper_page(maks. 100, bawaan 25 kecuali disebut lain), lalu mengembalikanmeta.page,meta.per_page,meta.total, danmeta.pages.
Batas request
- 120 request per menit per API key.
- Respons memuat header
X-RateLimit-LimitdanX-RateLimit-Remaining. - Lewat batas dibalas
429 rate_limiteddengan headerRetry-After(detik sampai menit berikutnya).
Kode error
| HTTP | code | Arti |
|---|---|---|
| 401 | unauthorized | API key tidak ada, formatnya salah, atau sudah dicabut; atau sesi aplikasi sudah berakhir. |
| 402 | plan_required | Workspace bukan Pro atau Custom yang aktif (API key dan fitur khusus Pro). |
| 403 | forbidden | Tidak punya permission, endpoint khusus aplikasi dipanggil dengan API key, atau key read mencoba mengubah data. |
| 404 | not_found | Endpoint atau data tidak ada, termasuk data milik workspace lain. |
| 405 | method_not_allowed | Method tidak didukung endpoint ini; lihat header Allow. |
| 409 | conflict / workspace_required | Data bentrok dengan keadaan sekarang (mis. role masih dipakai), atau pengguna belum punya workspace. |
| 419 | csrf_mismatch | Request aplikasi selain GET tanpa X-CSRF-Token yang valid. Muat ulang halaman lalu coba lagi. |
| 422 | validation_error | Input tidak valid; rincian per kolom ada di error.fields. |
| 423 | workspace_frozen | Workspace dibekukan karena kontrak Custom berhenti. Hanya Paket & Tagihan, pindah kepemilikan, notifikasi, dan data baca dasar yang tetap jalan. |
| 429 | rate_limited | Terlalu banyak request; tunggu sesuai Retry-After. |
| 502 | ai_error | Penyedia AI sedang gangguan. Kuota AI tidak berkurang; coba lagi sebentar. |
| 503 | ai_unavailable | Fitur AI belum diatur di server Onix. Hubungi admin Onix. |
| 500 | server_error | Gangguan di server. Aman dicoba lagi beberapa saat kemudian. |
Endpoint
Kolom Permission menunjukkan hak akses yang dibutuhkan pengguna aplikasi (diatur lewat role); "—" berarti semua anggota workspace. API key dianggap punya semua permission workspace dan melihat semua data.
Batas data (tim): permission mengatur menu & aksi, sedangkan data percakapan & tiket yang terlihat mengikuti tim. Percakapan yang belum di-assign terlihat semua yang punya interactions.view; yang di-assign ke tim Frontline hanya terlihat anggota tim itu; yang di-assign ke orang hanya terlihat orang itu. Tiket tanpa penanggung jawab terlihat anggota tim Back Office-nya; tiket dengan penanggung jawab hanya terlihat peserta (penanggung jawab, pembuat, yang di-@mention). Artikel knowledge base khusus tim hanya terlihat anggota tim yang dipilih (tanpa tim = semua tim). Lead pipeline tanpa PJ terlihat anggota tim lead-nya; lead ber-PJ hanya terlihat PJ-nya. Owner, role admin, dan anggota "Bisa lihat semua data" melihat semuanya (akses channel tetap berlaku). Data yang tidak boleh dilihat dibalas 404.
Bisa dipanggil dengan API key
| Endpoint | Permission | Keterangan |
|---|---|---|
GET /me | — | Pengguna, workspace aktif, role, permission, dan zona waktu efektif. Lewat API key: pengguna = pembuat key, via = "key". |
GET /workspace | — | Workspace aktif: nama, paket, masa aktif, zona waktu, dan batas paket. |
GET /dashboard | dashboard.view | Langkah awal, pemakaian kuota, aktivitas 14 hari, aktivitas terbaru, dan ringkasan tim (bagian tertentu butuh permission tambahan). |
GET /channels | — | Channel yang boleh diakses (type whatsapp/email/livechat/api, status, pengaturan, icon_url, hours = jam kerja sendiri atau null, auto_reply; livechat juga kunci publik & kode sematan, API juga URL webhook — tanpa kunci & secret), beserta kuota channel (gabungan semua jenis). |
GET /channels/{id}/icon | — | Ikon/logo unggahan channel (pengelola channel atau anggota dengan akses channel itu); 404 bila memakai ikon bawaan. |
GET /interactions | interactions.view | Inbox: percakapan per kind (chat/group) dan tab (new = belum dibalas sama sekali, waiting = menunggu balasan, unreplied = keduanya, replied, solved, closed). Setiap item punya reply_state. Filter channel_ids (satu atau beberapa id channel dipisah koma, mis. 1,3; channel_id lama tetap diterima), assignee (me/none/id), team (mine/none/id), label_id, contact_id, q, created_from/created_to (tanggal masuk, YYYY-MM-DD zona pembaca), category (id = kategori itu beserta semua subkategorinya, atau none). meta.counts = jumlah per tab; meta.teams = tim Frontline untuk filter. Di Pro/Custom setiap item punya sla (target balas dalam jam kerja: level warn/breach, menit, tenggat). Hanya percakapan yang boleh dilihat (batas data tim). |
GET /interactions/{id} | interactions.view | Satu percakapan: kontak/grup, channel, status, tim, assignee, label WhatsApp, waktu respons, custom_fields (field kustom interaction + nilainya), notes_count, tickets (SEMUA tiket dari percakapan ini — juga tanpa akses tiket — masing-masing dengan can_open, update_request, sla, dan thread dengan tim tiket), dan untuk pemegang contacts.view data & field kustom kontak (contact.details, contact.custom_fields). |
POST /interactions/{id}/tickets/{ticket}/messages | interactions.reply | Dari percakapan ke salah satu tiketnya (tanpa perlu akses tiket): {"text": "…"} mengirim pesan ke diskusi tiket; {"request_update": true} (teks opsional) meminta update — tiket menampilkan update_request sampai tim mengirim feedback/kesimpulan atau menyelesaikannya. Hanya tiket aktif (422), paling sering sekali per 15 menit per tiket (429). Hasil {"message", "tickets"}. |
GET /interactions/{id}/notes | interactions.view | Catatan internal percakapan (terbaru dulu, maks. 200), termasuk feedback & kesimpulan tiket (meta.source). Tulis catatan lewat POST /interactions/{id}/messages dengan type = note. |
GET /interactions/{id}/messages | interactions.view | Pesan urut lama → baru. Kursor before/after (id pesan), limit maks. 100. |
POST /interactions/{id}/messages | interactions.reply | Kirim pesan (scope write): {"text": "…"}, atau multipart/form-data dengan file. Jenis lain: note, sticker, location, contact; kutip dengan reply_to_id; template dengan template_id. Percakapan email: html (format minimal: tebal, miring, garis bawah, daftar, tautan; text dibuat otomatis), cc (dipisah koma, maks 10), reply_all, dan beberapa lampiran files[] (multipart, maks 10 file, total 20 MB); penerima, subjek "Re: …", kutipan email sebelumnya, dan tanda tangan diisi otomatis. Di nomor WhatsApp dengan inisial agen aktif, inisial pengirim ditambahkan di baris terakhir (tidak lewat API key). Percakapan livechat & channel API: teks, satu lampiran, atau catatan (tanpa kutip, stiker, lokasi, kontak); membalas livechat yang belum diambil sekaligus mengambilnya (tidak lewat API key). |
PATCH /interactions/{id} | interactions.reply | Ubah status (open/solved/closed), team_id (tim Frontline), assignee_id, category_id (kategori percakapan, null = tanpa kategori), dan/atau custom (field kustom interaction {kunci: nilai}; nilai kosong menghapus). Memindah tim atau menugaskan orang lain butuh interactions.assign; orang harus anggota tim percakapan (admin boleh tanpa tim). Hasil {"id", "visible": false} bila pemanggil tidak lagi boleh melihatnya. |
PATCH /interactions/{id}/messages/{message} | interactions.reply | Edit pesan teks sendiri (maks. 15 menit setelah dikirim). |
DELETE /interactions/{id}/messages/{message} | interactions.reply | Tarik pesan (hapus untuk semua), maks. 2 hari. |
POST /interactions/{id}/messages/{message}/retry | interactions.reply | Kirim ulang pesan yang gagal. |
POST /interactions/{id}/messages/{message}/reaction | interactions.reply | Reaksi emoji: {"emoji": "👍"}; kosong = hapus. |
GET /interactions/{id}/assignees | interactions.reply | Anggota yang bisa ditugaskan ke percakapan ini (dengan team_ids) dan tim Frontline beserta anggotanya di meta.teams. |
GET /messages/{id}/media | interactions.view | File media pesan (privat). Mendukung Range; ?download=1 untuk mengunduh. |
GET /messages/{id}/email | interactions.view | Email asli (HTML yang sudah dibersihkan, tanpa skrip) untuk ditampilkan di bingkai aman. Gambar dari internet diblokir; ?images=1 memuatnya. |
GET /messages/{id}/attachments/{index} | interactions.view | Lampiran email ke-index (mulai 0, urutan email.attachments pesan). ?download=1 untuk mengunduh. |
GET /contacts/{id}/avatar | interactions.view | Foto profil WhatsApp kontak. |
GET /groups/{id}/avatar | interactions.view | Foto grup WhatsApp. |
POST /interactions | interactions.reply | Mulai chat dengan kontak (scope write): {"contact_id", "channel_id", "text"}. Percakapan terbuka dengan kontak itu di nomor yang sama dipakai lagi. Channel email: wajib subject, isi html atau text, opsional cc; selalu membuat percakapan baru ke email kontak. |
POST /interactions/{id}/feedback-seen | interactions.view | Tandai feedback/kesimpulan tiket di percakapan sudah dibaca. |
GET /groups/{id} | interactions.view | Halaman grup: info, anggota (dicocokkan dengan kontak), dan percakapan grup. |
GET /tickets | tickets.view | Daftar tiket yang boleh dilihat (batas data tim). Filter status (active, open, …), priority, assignee (me/none/id), team (mine/id), q, contact_id, interaction_id, overdue. meta.counts = jumlah per status, meta.teams = tim Back Office untuk filter. |
POST /tickets | tickets.create | Buat tiket (scope write): subject, team_id (tim Back Office, wajib), assignee_ids (opsional, anggota tim itu), description, priority, due_date, interaction_id atau contact_id, dan custom (field kustom tiket {kunci: nilai}). Kuota tiket bulanan berlaku (402). |
GET /tickets/candidates | tickets.create | Anggota yang bisa ditugaskan atau disebut di tiket, dengan team_ids Back Office & is_admin. |
GET /tickets/{id} | tickets.view | Detail tiket, tim, peserta, izin pemanggil, custom_fields (field kustom tiket + nilainya), dan cuplikan percakapan asal. |
PATCH /tickets/{id} | tickets.manage | Ubah status, priority, due_date, subject, description, team_id (pindah tim melepas penanggung jawab yang bukan anggota tim baru), atau custom (field kustom tiket; field yang berubah dicatat di log). |
POST /tickets/{id}/assignees | tickets.manage | Tambah penanggung jawab (anggota tim tiket atau admin): {"user_id": 5}. |
DELETE /tickets/{id}/participants/{user} | tickets.manage | Keluarkan peserta (pengikut boleh berhenti mengikuti sendiri). Tanpa penanggung jawab, tiket kembali terlihat seluruh tim. |
GET /tickets/{id}/messages | tickets.view | Diskusi tiket + log di meta.events; after_message/after_event untuk yang baru saja. |
POST /tickets/{id}/messages | tickets.view | Kirim pesan diskusi: {"body": "…", "mention_ids": [5]}, atau multipart dengan files[] (maks. 5). @Nama di teks juga dikenali; yang disebut ikut melihat tiket. |
POST /tickets/{id}/messages/{message}/feedback | tickets.view | Kirim pesan diskusi sebagai feedback ke percakapan asal (catatan internal). |
POST /tickets/{id}/conclusion | tickets.view | Kesimpulan untuk agen: {"conclusion": "…", "resolve": true} (resolve butuh tickets.manage). |
GET /ticket-messages/{id}/files/{index} | tickets.view | Lampiran diskusi (privat). ?download=1 untuk mengunduh. |
GET /teams | — | Tim Frontline & Back Office beserta anggotanya; ?type=frontline|backoffice. |
GET /teams/{id} | — | Satu tim. |
GET /contacts | contacts.view | Daftar kontak. Filter q, label_id, wa_label_id, owner (me/none/id), channel_id, sort (recent/name/created). |
POST /contacts | contacts.manage | Tambah kontak: name, phone, email, company, job_title, address, city, language, owner_id, label_ids, custom. |
GET /contacts/{id} | contacts.view | Profil lengkap: identitas, label Onix & WhatsApp, field kustom, statistik & aktivitas 12 bulan. |
PATCH /contacts/{id} | contacts.manage | Ubah kontak (kolom yang dikirim saja). label_ids mengganti seluruh label. |
POST /contacts/{id}/labels | contacts.manage | Pasang label Onix: {"label_id": 3} (juga boleh dengan interactions.reply). |
DELETE /contacts/{id}/labels/{label} | contacts.manage | Lepas label Onix. |
GET /contacts/{id}/timeline | contacts.view | Linimasa kontak, terbaru dulu (before = id terakhir). |
GET /contacts/{id}/tickets | contacts.view | Tiket kontak beserta log statusnya (hanya yang boleh dilihat). |
GET /contacts/{id}/notes | contacts.view | Catatan tim. |
POST /contacts/{id}/notes | contacts.view | Tambah catatan: {"body": "…"}. |
PATCH /contacts/{id}/notes/{note} | contacts.view | Ubah catatan (hanya penulisnya). |
DELETE /contacts/{id}/notes/{note} | contacts.view | Hapus catatan (penulisnya atau contacts.manage). |
GET /labels | contacts.view | Label Onix beserta jumlah kontaknya; meta.colors = warna yang tersedia. |
GET /custom-fields | contacts.view / interactions.view / tickets.view / leads.view | Definisi field kustom per entitas: ?entity=contact|interaction|ticket|lead|client (tanpa entity = semua). meta.max_per_entity = 30. |
GET /contact-fields | contacts.view | Definisi field kustom kontak (sama dengan /custom-fields?entity=contact). |
GET /wa-label-rules | contacts.manage | Aturan otomasi label WhatsApp (Pro): {"label_name", "channel", "action", "value", "value_label", "active"}. Juga boleh dengan channels.manage. |
GET /conversation-categories | interactions.view | Kategori percakapan dalam urutan pohon (induk lalu subkategorinya): {"id", "name", "color", "position", "parent_id", "depth", "path_text", "children_count"}. Juga boleh dengan contacts.view. |
GET /kb/categories | kb.view | Kategori knowledge base (urut posisi) dengan jumlah artikel terbit yang boleh dilihat pemanggil. |
POST /kb/categories | kb.manage | Buat kategori: {"name", "description", "position"}. Nama unik per workspace. |
PATCH /kb/categories/{id} | kb.manage | Ubah kategori (kolom yang tidak dikirim tetap). |
DELETE /kb/categories/{id} | kb.manage | Hapus kategori; artikelnya menjadi tanpa kategori. |
GET /kb/articles | kb.view | Daftar artikel berhalaman. Filter q (setiap kata wajib ada), category_id (id atau none), visibility, status, team_id (id tim = artikel khusus tim itu, none = untuk semua tim). Tanpa kb.manage hanya artikel terbit. Artikel khusus tim hanya untuk anggota tim itu (Owner, admin, "Bisa lihat semua data", dan API key melihat semua). Setiap artikel punya teams (kosong = semua tim). meta.counts = jumlah terbit & draf. |
POST /kb/articles | kb.manage | Buat artikel: {"title", "body", "category_id", "visibility", "status", "tags", "team_ids"}. Bawaan Internal + Draf, untuk semua tim. Isi = Markdown sederhana. team_ids = tim yang boleh membaca; pengelola yang tidak melihat semua data hanya boleh memilih timnya sendiri (422). |
GET /kb/articles/{id} | kb.view | Satu artikel lengkap dengan isi, teams, status pemrosesan pencarian makna (embedding_status, chunk_count, embedded_at_text), dan can.insert (artikel Publik terbit boleh disisipkan ke balasan). Artikel khusus tim lain → 404. |
PATCH /kb/articles/{id} | kb.manage | Ubah artikel (kolom yang tidak dikirim tetap; team_ids: [] = semua tim). Terbit & judul/isi berubah → diproses ulang untuk pencarian makna. |
DELETE /kb/articles/{id} | kb.manage | Hapus artikel. |
GET /kb/search | kb.view | Cari artikel terbit. mode=keyword (bawaan, semua paket) atau mode=semantic (Pro/Custom, ai.use, 1 kuota AI per pencarian). Parameter q, visibility, limit (1–20). Hasil: {"article", "match", "score", "snippet"}; meta.ai = pemakaian AI bulan ini. |
GET /reports/summary | reports.view | Kartu ringkasan untuk rentang from–to (YYYY-MM-DD menurut zona pembaca, inklusif; bawaan 30 hari terakhir, maks 366 hari) dan filter opsional channel_id, team_id: percakapan masuk, pesan masuk/keluar, respons pertama (rata-rata, median, % dalam target), waktu penyelesaian, belum dibalas sekarang, tiket. Rumus: Rumus laporan. |
GET /reports/daily | reports.view | Satu baris per tanggal dalam rentang: {"date", "conversations", "messages_in", "messages_out"} (0 bila kosong). Parameter sama dengan ringkasan. |
GET /reports/hourly | reports.view | 24 baris pesan masuk per jam 0–23 (zona pembaca): {"hour", "messages_in"}. |
GET /reports/breakdown | reports.view | type = channel, label, category, atau team: baris per kelompok dengan jumlah percakapan masuk (per nomor juga pesan & rata-rata respons pertama; per tim juga tiket dibuat/selesai; per kategori urut pohon dengan conversations termasuk subkategori dan conversations_direct). |
GET /kpi | reports.view | Kartu KPI per orang (Pro/Custom; Free → 402): frontline (respons pertama, balasan lanjutan, penyelesaian, Solved per hari kerja, kontak kembali, eskalasi, lewat target sekarang) dan backoffice (respons tiket, penyelesaian tepat waktu per prioritas, selesai per hari kerja, dibuka lagi, feedback, backlog). Waktu dalam menit/jam kerja; from/to (zona workspace, maks 93 hari), team_id, channel_type (whatsapp/email/livechat/api: hanya percakapan & tiket dari jenis channel itu, dengan target jenis itu — email, livechat, dan API punya target sendiri). Lihat KPI & SLA. |
GET /kpi/users/{id} | — | KPI satu orang dengan daily, breaches, dan targets (beserta sumbernya). Diri sendiri selalu; orang lain butuh reports.view. |
GET /kpi/me | — | KPI-mu hari ini & 7 hari terakhir (kartu "KPI saya" di Dashboard). |
GET /kpi/config | settings.workspace | Target workspace, target tim & orang, daftar metrik (termasuk target email email_first_response & email_reply dalam jam, livechat livechat_first_response & livechat_reply dan channel API api_first_response & api_reply dalam menit), dan jam kerja workspace. |
GET /reports/agents | reports.view | Produktivitas setiap anggota aktif: {"user", "replies", "conversations", "first_responses", "avg_first_response_minutes", "tickets_resolved"}. |
POST /interactions/{id}/summary | ai.use | Ringkasan AI percakapan (Pro/Custom, 1 kuota AI): 3–6 poin, disimpan dan terlihat di GET /interactions/{id} → ai_summary. |
GET /templates | interactions.reply | Template balasan. Dengan interaction_id, tiap template membawa rendered (variabel terisi). Filter q, category. |
GET /templates/{id} | interactions.reply | Satu template. |
GET /templates/{id}/attachment | interactions.reply | Lampiran template. |
GET /settings | settings.workspace | Pengaturan General (zona waktu workspace, target respons, jam kerja business_hours + open_now, …) dan pilihannya di meta.choices. |
GET /members | settings.members | Semua anggota termasuk Owner. |
GET /invitations | settings.members | Undangan yang belum diterima, termasuk yang kedaluwarsa. |
GET /roles | settings.roles | Semua role beserta permission dan jumlah pemakai (atau settings.members). |
GET /roles/{id} | settings.roles | Satu role. |
GET /permissions | settings.roles | Katalog permission per kelompok menu; meta.grantable = yang boleh diberikan pengguna ini. |
GET /audit-logs | settings.audit | Audit log terbaru dulu. Filter: category, user, from, to (YYYY-MM-DD, zona pembaca), q. Bawaan 50 per halaman. |
GET /pipelines | leads.view / leads.manage | Workflow pipeline yang terlihat (admin, "lihat semua data", API key, dan pipeline.manage: semua; selain itu workflow tim pemanggil): tahap (kind new/progress/won/lost, label, warna, probability) dan tim Back Office yang menangani. meta = alasan kalah, kategori biaya, palet warna. |
GET /pipelines/{id} | leads.view / leads.manage | Satu workflow (pemegang pipeline.manage juga mendapat jumlah lead per tahap). |
GET /pipeline/settings | leads.view / leads.manage | Alasan kalah, kategori biaya, palet warna tahap, dan batas tahap Proses. |
GET /pipeline/dashboard | leads.view / leads.manage | Dashboard pipeline: tiles (terbuka, perkiraan, baru 7 hari, menang/kalah, win rate, rata-rata hari closing, follow-up lewat), funnel, weekly (8 minggu), by_assignee, expenses, agenda hari ini, quota. Saringan pipeline_id, from/to (bawaan bulan berjalan), team_id, assignee_id. Hanya lead yang boleh dilihat. |
GET /leads | leads.view / leads.manage | Daftar lead (kepemilikan data: lead ber-PJ hanya untuk PJ-nya, tanpa PJ untuk tim lead; admin/API key semua). Saringan pipeline_id, stage_id, status (open/won/lost), team_id, assignee (me/none/id), client_id, contact_id, q (LEAD-…, judul, kontak, klien), followup (overdue/today/upcoming/none), created_from/created_to; sort & dir. meta.totals = jumlah, nilai prospek, nilai deal. |
POST /leads | leads.manage | Buat lead (create_lead; sumber api): pipeline_id, title, kontak (contact_id, atau contact {name, phone, email} dicocokkan lewat nomor HP lalu email, atau interaction_id), client_id/client_name, stage_id, team_id, assignee_id, value_estimate, budget, expected_close, followup_at, note, custom. Kuota lead bulanan berlaku (402). |
GET /leads/board | leads.view / leads.manage | Papan kanban satu workflow (pipeline_id wajib): tahap + kartu lead terbuka & Menang/Kalah bulan berjalan (maks 100 per tahap, more), count/value per tahap, dan summary. |
GET /leads/candidates | leads.view / leads.manage | Anggota yang bisa menjadi PJ, dengan team_ids Back Office & is_admin. |
GET /leads/duplicates | leads.manage | Lead terbuka kontak di workflow yang sama (contact_id, pipeline_id) — peringatan sebelum membuat lead. |
GET /leads/{id} | leads.view / leads.manage | Detail lead: workflow & tahap, kontak, klien, percakapan asal, 30 aktivitas terbaru, checklist, jadwal, file, biaya, field kustom, dan can. |
PATCH /leads/{id} | leads.manage | Ubah title, client_id/client_name, value_estimate, value_won (lead Menang), budget, expected_close, followup_at/followup_note (null = hapus), team_id, assignee_id, lost_reason/lost_note (lead Kalah), custom. Hasil {"id", "visible": false} bila pemanggil tidak lagi boleh melihatnya. |
POST /leads/{id}/move | leads.manage | Pindah tahap: {"stage_id"}; ke Menang wajib value_won (bawaan nilai prospek), ke Kalah wajib lost_reason dari daftar (+ lost_note). Dari Menang/Kalah ke tahap Baru/Proses = buka lagi. |
GET /leads/{id}/activities | leads.view / leads.manage | Linimasa lead berhalaman (before = id terakhir, kind=note untuk catatan saja). |
POST /leads/{id}/activities | leads.manage | Catat aktivitas: {"kind": "call|chat|email|meeting|visit|note|other", "body", "happened_at", "duration_minutes"}. @Nama memberi notifikasi. |
GET /lead-files/{id} | leads.view / leads.manage | File lead (privat). ?download=1 untuk mengunduh. |
GET /lead-expenses/{id}/receipt | leads.view / leads.manage | Bukti biaya (privat). ?download=1 untuk mengunduh. |
GET /interactions/{id}/leads | interactions.view | Tab Leads percakapan: SEMUA lead dari percakapan ini (ringkas, can_open) + lead terbuka lain kontaknya yang boleh dilihat. |
GET /contacts/{id}/leads | contacts.view | Lead kontak yang boleh dilihat (kosong tanpa akses Pipeline). |
GET /clients | contacts.view / leads.view | Master klien (tidak dibatasi tim): q, industry; setiap klien dengan contacts_count dan ringkasan lead yang boleh dilihat. meta.industries untuk saringan. |
GET /clients/search | contacts.view / leads.view | Cari klien untuk pilihan di form: ?q=. |
POST /clients | clients.manage | Tambah klien: {"name", "industry", "phone", "email", "website", "address", "city", "notes", "custom"}. Nama unik per workspace. |
GET /clients/{id} | contacts.view / leads.view | Profil klien, kontak tertaut, lead yang boleh dilihat, dan ringkasan deal. |
PATCH /clients/{id} | clients.manage | Ubah klien. |
GET /segments | broadcasts.view / broadcasts.manage | Segmen kontak: aturan, ringkasan, last_count, jumlah broadcast yang memakainya. |
GET /segments/fields | broadcasts.view / broadcasts.manage | Katalog field, operator, & pilihan nilai untuk aturan segmen (termasuk field kustom cf:{kunci}). |
POST /segments/preview | broadcasts.view / broadcasts.manage | Pratinjau aturan tanpa menyimpan: {"match": "all|any", "rules": [{"field", "op", "value", "value2"}]} → jumlah, punya nomor, berhenti berlangganan, contoh. |
GET /segments/{id} | broadcasts.view / broadcasts.manage | Detail segmen + hitung ulang isinya (preview). |
GET /broadcasts | broadcasts.view / broadcasts.manage | Daftar broadcast (status, channel_id, q) dengan angka per status (stats). |
GET /broadcasts/options | broadcasts.view / broadcasts.manage | Nomor (izin broadcast), segmen, pengaturan bawaan & batas aman, kuota, variabel pesan. |
GET /broadcasts/dashboard | broadcasts.view / broadcasts.manage | Angka periode (from, to, channel_id; maks 92 hari): corong, harian, per jam, alasan, pemakaian nomor hari ini, broadcast terbaru & terbaik. |
GET /broadcasts/{id} | broadcasts.view / broadcasts.manage | Detail broadcast: audiens, pesan, lampiran, pengaturan, angka, alasan dilewati, persetujuan risiko, wait, can. |
GET /broadcasts/{id}/recipients | broadcasts.view / broadcasts.manage | Penerima & status per penerima (status bertingkat, q), termasuk isi pesan yang terkirim. |
GET /broadcasts/{id}/export | broadcasts.view / broadcasts.manage | Laporan per penerima ?format=xlsx|csv. |
GET /broadcasts/{id}/media | broadcasts.view / broadcasts.manage | Lampiran broadcast (privat). |
POST /broadcasts/{id}/estimate | broadcasts.view / broadcasts.manage | Perkiraan penerima (alasan dilewati), kuota, waktu selesai, dan tingkat risiko. |
POST /broadcasts/{id}/preview | broadcasts.view / broadcasts.manage | Teks jadi untuk maks 5 kontak contoh (variant, opsional text/footer). |
Khusus aplikasi Onix
Endpoint berikut hanya menerima sesi aplikasi (cookie + X-CSRF-Token). Dengan API key dibalas 403 forbidden.
| Endpoint | Permission | Keterangan |
|---|---|---|
POST /wa-label-rules | contacts.manage | Buat aturan label WhatsApp (Pro): action = contact_label (value = id label kontak), assign_team (id tim Frontline), atau solve. Free → 402. |
PATCH /wa-label-rules/{id} | contacts.manage | Ubah aturan (termasuk active). |
DELETE /wa-label-rules/{id} | contacts.manage | Hapus aturan. |
POST /conversation-categories | contacts.manage | Buat kategori percakapan: {"name", "color", "parent_id"} — sampai 3 tingkat dan 200 kategori; nama unik di antara saudara. |
PATCH /conversation-categories/{id} | contacts.manage | Ubah nama, warna, urutan, atau induk kategori (parent_id, null = kategori utama; tidak ke dirinya/subkategorinya, maks 3 tingkat). |
DELETE /conversation-categories/{id} | contacts.manage | Hapus kategori; subkategori & percakapannya pindah ke induknya (tanpa kategori bila kategori utama). |
PUT /kpi/config | settings.workspace | Simpan target workspace (targets) dan/atau target tim & orang (overrides, mengganti semuanya). Jam kerja kini diatur lewat PATCH /settings (business_hours di sini tetap diterima). |
GET /kpi/export | reports.view | CSV KPI: type = summary, conversations, replies, atau tickets; user_id untuk satu orang (boleh untuk dirimu sendiri tanpa reports.view); channel_type seperti di atas. Data mentah punya kolom channel_type di akhir. |
POST /kb/articles/{id}/embed | kb.manage | Proses (ulang) artikel terbit untuk pencarian makna (Pro/Custom) — tombol Proses sekarang / Proses ulang / Coba lagi. |
GET /reports/export | reports.view | Unduh CSV (UTF-8 + BOM): type = summary, daily, channel, label, category, agents, atau tickets, dengan rentang & filter yang sama seperti laporan JSON. |
PATCH /me | — | Bahasa & zona waktu pribadi: {"locale": "id", "timezone": "Asia/Makassar"} ("" = ikut workspace). |
POST /me/preferences | — | Preferensi pribadi, mis. status tur, sidebar, dan livechat_alert (0/1: bunyi & judul tab berkedip saat chat livechat baru menunggu). |
GET /me/invitations | — | Undangan berlaku untuk email akun ini. |
POST /me/invitations/{id}/accept | — | Terima undangan; workspace itu menjadi workspace aktif. |
POST /me/workspace | — | Pindah workspace aktif: {"workspace_id": 3}. |
GET /workspaces | — | Workspace tempat pengguna menjadi anggota aktif. |
POST /workspaces | — | Buat workspace: {"name": "…", "timezone": "Asia/Jakarta"}. Akun Free/Pro memiliki satu workspace; pelanggan Custom sesuai jatah kontraknya (409). meta.create di GET /workspaces menunjukkan boleh/tidaknya. |
GET /workspace/transfer | — | Pindah kepemilikan (khusus Owner): permintaan yang menunggu + calon penerima dan kelayakannya. |
POST /workspace/transfer | — | Minta pindah kepemilikan: to_user_id, confirm_name (nama workspace), stay, stay_role_id, stay_team_ids. |
DELETE /workspace/transfer | — | Batalkan permintaan yang menunggu. |
GET /me/transfers | — | Permintaan pindah kepemilikan yang menunggu jawabanku. |
GET /me/transfers/{id} | — | Detail permintaan (can_accept, becomes_free). |
POST /me/transfers/{id}/accept | — | Terima: aku menjadi Owner; workspace itu menjadi workspace aktif. |
POST /me/transfers/{id}/decline | — | Tolak permintaan. |
PATCH /workspace | settings.workspace | Ganti nama workspace. |
POST /workspace/leave | — | Keluar dari workspace aktif (bukan Owner). |
PATCH /settings | settings.workspace | Ubah sebagian pengaturan General, mis. {"timezone": "Asia/Jakarta"} atau jam kerja workspace (semua paket) {"business_hours": {"enabled": true, "days": [{"day": 1, "open": true, "from": "08:00", "to": "17:00"}, …]}} — hari 1 = Senin. |
GET /notifications | — | 20 notifikasi terbaru dan jumlah yang belum dibaca. |
POST /notifications/read | — | Tandai satu ({"id": 12}) atau semua notifikasi dibaca. |
POST /realtime/token | — | Token WebSocket (Centrifugo) untuk pembaruan langsung; {"channels": ["conv:12", "ticket:5"]} untuk ikut kanal percakapan/tiket. |
POST /interactions/{id}/read | interactions.view | Tandai dibaca; tanda biru dikirim ke pelanggan. |
POST /interactions/{id}/typing | interactions.reply | Indikator mengetik: {"typing": true}. |
POST /interactions/{id}/pickup | interactions.reply | Ambil chat livechat yang belum diambil (atomik): yang kalah cepat mendapat 409 "Sudah diambil oleh {nama}". Pengunjung melihat "{nama} bergabung ke chat". |
POST /interactions/{id}/history | interactions.view | Salin riwayat lama dari HP untuk percakapan ini. |
POST /channels | channels.manage | Tambah nomor WhatsApp: {"name": "CS Toko"} (kuota channel dicek). grant_selected_members: true = anggota yang aksesnya "channel tertentu" ikut diberi akses (juga di POST /channels/email, /livechat, /api). |
GET /channels/{id} | channels.manage | Detail channel. |
PATCH /channels/{id} | channels.manage | Semua jenis channel: name, jam kerja hours (objek seperti business_hours, atau null = ikuti jam kerja workspace), balasan otomatis auto_reply (greeting_on, greeting, away_on, away). WhatsApp: groups, reject_calls, call_reply, agent_initial (tambahkan inisial agen di akhir balasan). Pengaturan email/livechat/API lainnya lewat PATCH /channels/{id}/email, /livechat, /api. |
DELETE /channels/{id} | channels.manage | Hapus channel (diarsipkan bila sudah punya percakapan). |
GET /channels/{id}/qr | channels.manage | QR untuk scan (data URL PNG) + umur dalam detik. |
POST /channels/{id}/pair | channels.manage | Kode pairing: {"phone": "0812…"}. |
GET /channels/{id}/status | channels.manage | Status terbaru nomor. |
POST /channels/{id}/logout | channels.manage | Logout nomor dari Onix. |
POST /channels/{id}/reconnect | channels.manage | Sambung ulang koneksi. |
POST /channels/{id}/history | channels.manage | Impor riwayat chat: {"days": 30} (7/30/90 hari). |
GET /channels/{id}/labels | channels.manage | Label WhatsApp Business (dibaca dari HP). |
POST /channels/email/detect | channels.manage | Tebak penyedia dari alamat: {"address": "[email protected]"} → provider, saran server IMAP/SMTP, dan petunjuk (mis. butuh App Password; Microsoft 365 belum didukung). Hanya sesi login. |
POST /channels/email/test | channels.manage | Tes login IMAP & SMTP tanpa mengirim email: address, password, opsional username, imap_host/imap_port/imap_security (ssl/starttls), smtp_host/smtp_port/smtp_security, smtp_username/smtp_password. Hasil: folder yang bisa dipilih, folder Terkirim terdeteksi. Kesalahan dijelaskan per kolom (422). |
POST /channels/email | channels.manage | Sambungkan alamat email (kuota channel dicek; satu alamat hanya di satu workspace → 409): isian tes di atas + name, folders (selain Inbox), sent_folder, read_sent, save_sent, history_days (0/3/7/30, bawaan 7), sender_name, sender_with_agent, signature_html, ignore. Password disimpan terenkripsi dan tidak pernah dikembalikan. |
PATCH /channels/{id}/email | channels.manage | Ubah pengaturan email (kolom sama dengan di atas, kecuali history_days). Perubahan server, username, password, atau folder dites ulang sebelum disimpan. |
GET /channels/{id}/email/folders | channels.manage | Daftar folder kotak surat (login ulang) dengan tanda selected, plus folder Terkirim. |
POST /channels/{id}/sync | channels.manage | Periksa kotak surat sekarang (jeda setelah login gagal diabaikan). Hasil {"sync", "channel"}. |
POST /channels/{id}/icon | channels.manage | Unggah ikon/logo channel (multipart icon: PNG/JPG/WebP persegi, maks 512 KB). Livechat: logo yang sama tampil di kepala widget & peluncur. |
DELETE /channels/{id}/icon | channels.manage | Kembali ke ikon bawaan jenis channel. |
POST /channels/livechat | channels.manage | Buat channel livechat (semua paket, satu slot channel): {"name": "Chat Website", "title", "color", "grant_selected_members"} → channel dengan livechat.key & livechat.embed_code. Lihat Livechat. |
PATCH /channels/{id}/livechat | channels.manage | Pengaturan widget: title, subtitle, color, font, radius, position, launcher_icon, intro, consent, start_label, attachments (off/images/files), email_fallback, allowed_domains; juga name, hours, auto_reply. |
POST /channels/{id}/livechat/key | channels.manage | Ganti kunci publik; kode sematan lama berhenti bekerja. |
POST /channels/api | channels.manage | Buat channel API (Pro/Custom, satu slot channel): {"name", "webhook_url", "events", "retries", "grant_selected_members"} → credentials.key (hanya tampil sekali) & credentials.webhook_secret. Lihat Channel API. |
GET /channels/{id}/api | channels.manage | Pengaturan, endpoint pesan masuk, kunci aktif (awalan & terakhir dipakai), dan 50 pengiriman webhook terbaru. |
PATCH /channels/{id}/api | channels.manage | webhook_url (https, host publik), events (message.created selalu; conversation.updated opsional), retries (0–5); juga name, hours, auto_reply. |
POST /channels/{id}/api/key | channels.manage | Ganti kunci channel; kunci lama langsung ditolak (401). |
GET /channels/{id}/api/secret | channels.manage | Lihat secret webhook. |
POST /channels/{id}/api/secret | channels.manage | Ganti secret webhook. |
POST /channels/{id}/api/test-webhook | channels.manage | Kirim event ping sekarang: {"status", "http_status", "duration_ms", "error"}. |
POST /channels/{id}/api/test-message | channels.manage | Simulasikan pesan masuk dari sistem Anda (tampil di Interaction). |
POST /templates | templates.manage | Buat template: name, shortcut, category, body (JSON atau multipart dengan file). |
PATCH /templates/{id} | templates.manage | Ubah template. |
DELETE /templates/{id} | templates.manage | Hapus template. |
POST /templates/{id}/attachment | templates.manage | Pasang/ganti lampiran (multipart file). |
DELETE /templates/{id}/attachment | templates.manage | Lepas lampiran. |
GET /contacts/export | contacts.manage | Ekspor kontak ke CSV (filter sama dengan daftar). |
POST /contacts/import | contacts.manage | Impor CSV (multipart file): hasil created, updated, skipped, errors. |
DELETE /contacts/{id} | contacts.manage | Hapus kontak beserta percakapan, pesan, media, catatan, dan linimasanya (tiket tetap ada tanpa tautan). |
POST /contacts/{id}/merge | contacts.manage | Gabung kontak ganda: {"source_id": 9} dilebur ke kontak {id}. |
POST /labels | contacts.manage | Buat label: {"name": "VIP", "color": "orange"}. |
PATCH /labels/{id} | contacts.manage | Ubah nama, warna, atau urutan label. |
DELETE /labels/{id} | contacts.manage | Hapus label (dilepas dari semua kontak). |
POST /custom-fields | contacts.manage | Buat field kustom kontak, interaction, atau tiket: {"entity": "interaction", "label": "Nomor invoice", "type": "text"}. Kunci unik per entitas. |
PATCH /custom-fields/{id} | contacts.manage | Ubah nama, pilihan, atau urutan field (entitas, jenis, & kunci tetap). |
DELETE /custom-fields/{id} | contacts.manage | Hapus field kustom; nilainya tidak lagi tampil. |
POST /contact-fields | contacts.manage | Buat field kustom kontak: {"label": "Ukuran", "type": "select", "options": ["S", "M", "L"]}. |
PATCH /contact-fields/{id} | contacts.manage | Ubah nama, pilihan, atau urutan field. |
DELETE /contact-fields/{id} | contacts.manage | Hapus field kustom. |
PATCH /members/{id} | settings.members | Ubah role, team_ids, view_all, akses channel, atau status (active/disabled). Role bukan admin wajib minimal satu tim. reply_initial (maks 20 karakter, kosong = otomatis dari nama, mis. ^BS) boleh diatur untuk semua anggota termasuk Owner. |
POST /invitations | settings.members | Undang anggota: email, role_id, team_ids, view_all, channel_access, channel_ids. |
POST /teams | settings.members | Buat tim: {"name": "Gudang", "type": "backoffice", "member_ids": [5, 7]}. |
PATCH /teams/{id} | settings.members | Ubah nama, deskripsi, atau anggota tim (member_ids = daftar lengkap). Jenis tidak bisa diubah. |
DELETE /teams/{id} | settings.members | Hapus tim; bila masih punya anggota/data (termasuk artikel KB khusus tim) wajib ?replacement_id= tim sejenis. |
POST /invitations/{id}/resend | settings.members | Kirim ulang undangan dengan tautan baru. |
DELETE /invitations/{id} | settings.members | Batalkan undangan. |
POST /roles | settings.roles | Buat role: name, permissions, dan is_admin (hanya Owner/admin). |
PATCH /roles/{id} | settings.roles | Ubah nama, permission, dan tanda is_admin role (kecuali Owner). |
DELETE /roles/{id} | settings.roles | Hapus role yang tidak dipakai siapa pun. |
POST /roles/{id}/duplicate | settings.roles | Salin role. |
GET /api-keys | settings.api | API key aktif, tanpa nilai rahasianya. |
POST /api-keys | settings.api | Buat key: {"name": "…", "scope": "read"}. Nilai utuh hanya dikembalikan sekali. |
DELETE /api-keys/{id} | settings.api | Cabut key. |
GET /billing | settings.billing | Paket, pemakaian, invoice, dan profil tagihan. |
POST /billing/upgrade | settings.billing | Terbitkan/pakai invoice upgrade lalu buat checkout Sassly Pay. |
GET /billing/invoices/{number} | settings.billing | Detail invoice beserta riwayat percobaan bayar. |
POST /billing/invoices/{number}/pay | settings.billing | Alamat checkout Sassly Pay (percobaan yang masih berlaku dipakai ulang). |
PATCH /billing/profile | settings.billing | Profil tagihan untuk invoice berikutnya. |
POST /billing/downgrade-choice | settings.billing | Pilih channel & anggota yang tetap aktif setelah turun ke Free. |
GET /billing/return | settings.billing | Status pembayaran setelah kembali dari checkout (dicek ke Sassly Pay di server). |
POST /pipelines | pipeline.manage | Buat workflow: {"name", "description", "team_ids"} (tim Back Office); tanpa stages → tahap bawaan. |
PATCH /pipelines/{id} | pipeline.manage | Ubah nama, deskripsi, tim, urutan; {"archived": false} memulihkan. |
PUT /pipelines/{id}/stages | pipeline.manage | Simpan susunan tahap lengkap: satu Baru, 0–10 Proses, satu Menang, satu Kalah (label, warna, peluang %). |
DELETE /pipelines/{id} | pipeline.manage | Hapus workflow tanpa lead; yang masih punya lead diarsipkan. |
PUT /pipeline/settings | pipeline.manage | Simpan lost_reasons & expense_categories. |
GET /pipeline/export | reports.view | CSV raw data: type = leads (semua kolom + field kustom), activities, atau expenses; saringan pipeline_id, status, from/to. |
GET /leads/import/template | leads.manage | Template impor ?format=xlsx|csv. |
POST /leads/import/preview | leads.manage | Baca file Excel/CSV (multipart file): kolom, contoh isi, saran pemetaan, token 1 jam. |
POST /leads/import | leads.manage | Periksa (dry_run) atau jalankan impor dengan pemetaan kolom (kolom tanpa padanan → field kustom baru). |
POST /leads/bulk | leads.manage | Aksi massal (maks 100): move, assign, followup. |
DELETE /leads/{id} | leads.manage | Hapus lead (admin, PJ, atau pembuat); kuota tidak kembali. |
PATCH /lead-activities/{id} | leads.manage | Ubah aktivitas manual (penulis atau admin). |
DELETE /lead-activities/{id} | leads.manage | Hapus aktivitas manual (penulis atau admin). |
POST /leads/{id}/files | leads.manage | Unggah file lead (multipart file). |
DELETE /lead-files/{id} | leads.manage | Hapus file (pengunggah, PJ, atau admin). |
POST /leads/{id}/checklist | leads.manage | Tambah butir checklist {"text"}; PATCH /lead-checklist/{id} (text, done, position) dan DELETE /lead-checklist/{id}. |
PATCH /lead-checklist/{id} | leads.manage | Ubah / centang butir checklist. |
DELETE /lead-checklist/{id} | leads.manage | Hapus butir checklist. |
POST /leads/{id}/events | leads.manage | Tambah jadwal: {"kind", "title", "starts_at", "ends_at", "location", "notes", "remind_minutes"}. |
PATCH /lead-events/{id} | leads.manage | Ubah jadwal (mengubah waktu mulai mengatur ulang pengingat). |
DELETE /lead-events/{id} | leads.manage | Hapus jadwal. |
POST /leads/{id}/expenses | leads.manage | Catat biaya (multipart): spent_on, category, amount, note, spent_by, receipt (foto/PDF). |
PATCH /lead-expenses/{id} | leads.manage | Ubah biaya (pencatat, pembayar, atau admin). |
DELETE /lead-expenses/{id} | leads.manage | Hapus biaya beserta buktinya. |
DELETE /clients/{id} | clients.manage | Hapus klien; kontak & lead tetap ada tanpa tautan klien. |
POST /clients/{id}/contacts | clients.manage | Tautkan ({"contact_id", "link": true}) atau lepas kontak; lead kontak yang belum berklien ikut tertaut. |
POST /contacts/{id}/broadcast-opt-out | contacts.manage / broadcasts.manage | Berhenti ({"opt_out": true}) atau kembali berlangganan broadcast. |
POST /segments | broadcasts.manage | Buat segmen: {"name", "description", "match", "rules"} (maks 15 aturan, nama unik). |
PATCH /segments/{id} | broadcasts.manage | Ubah segmen. |
DELETE /segments/{id} | broadcasts.manage | Hapus segmen (ditolak bila dipakai broadcast yang terjadwal/berjalan/dijeda). |
GET /segments/{id}/export | broadcasts.manage | Unduh isi segmen (CSV). |
POST /broadcasts | broadcasts.manage | Buat draf (Pro/Custom): {"name", "channel_id", "audience", "messages", "settings"}. |
PATCH /broadcasts/{id} | broadcasts.manage | Ubah draf (bagian yang dikirim saja). |
DELETE /broadcasts/{id} | broadcasts.manage | Hapus draf, broadcast selesai, atau dibatalkan. |
POST /broadcasts/{id}/media | broadcasts.manage | Pasang lampiran (multipart file: gambar, video, dokumen); DELETE untuk melepas. |
POST /broadcasts/{id}/test | broadcasts.manage | Kirim uji ke satu nomor {"phone", "variant"} (tidak memakai kuota, dibatasi per jam). |
POST /broadcasts/{id}/schedule | broadcasts.manage | Mulai sekarang/jadwalkan dengan {"risk_ack": true}; daftar penerima dikunci. |
POST /broadcasts/{id}/pause | broadcasts.manage | Jeda. Juga /resume, /cancel, /retry (kirim ulang yang gagal), /unschedule (kembali ke draf), /duplicate. |
Publik
| Endpoint | Permission | Keterangan |
|---|---|---|
GET /public/config | — | Harga & kuota paket, pajak, dan aturan retensi (mengikuti X-Locale). |
GET /public/demo-livechat | — | Kunci livechat data contoh untuk halaman /demo/livechat (null bila belum ada). |
POST /plan-requests | — | Permintaan paket Custom: name, email, message, opsional company, phone, channels, agents. |
GET /invite/{token} | — | Ringkasan undangan dari tautan email. |
Widget livechat (publik)
Dipanggil widget livechat (pemuat livechat.js & iframe Onix) tanpa login. {key} = kunci publik channel. Selain config dan logo, semua memakai token pengunjung di Authorization: Bearer. Penjelasan lengkap: Livechat.
| Endpoint | Akses | Keterangan |
|---|---|---|
GET /livechat/{key}/config | — | Tampilan & teks widget, status jam kerja, token formulir (CORS *). |
GET /livechat/{key}/logo | — | Logo widget. |
POST /livechat/{key}/visitors | — | Mulai chat: name, email, phone (wajib), page_url, locale, form_token → token pengunjung. |
GET /livechat/{key}/conversation | — | Percakapan pengunjung + pesan sesudah ?after={id}, posisi antrian, agen. |
POST /livechat/{key}/messages | — | Kirim pesan: text, client_id (kirim ulang aman), opsional lampiran multipart file. |
GET /livechat/{key}/files/{id} | — | Lampiran di percakapan pengunjung itu saja. |
POST /livechat/{key}/realtime | — | Token WebSocket kanal visitor:{sesi}. |
POST /livechat/{key}/typing | — | Pengunjung sedang mengetik. |
POST /livechat/{key}/seen | — | Widget terbuka & pesan sampai message_id sudah dilihat. |
Channel API (kunci channel)
Untuk sistem Anda yang mengirim pesan pelanggan ke Onix lewat channel API, dengan kunci channel onx_ch_… di Authorization: Bearer (bukan API key workspace). Balasan agen dikirim ke webhook Anda. Panduan, contoh payload, dan verifikasi tanda tangan: Channel API.
| Endpoint | Akses | Keterangan |
|---|---|---|
POST /channel-api/messages | — | Pesan masuk: {"conversation_id", "contact": {"id", "name", "email", "phone"}, "message": {"id", "text", "attachments", "sent_at"}}. message.id unik → kirim ulang aman. |
POST /channel-api/messages/{id}/status | — | Tandai balasan agen delivered/read. |
GET /channel-api/files/{token} | — | Lampiran balasan agen (tautan bertanda tangan di webhook, 7 hari). |
Contoh
Siapa pemilik key ini
curl -s "https://onix.sassly.ai/api/v1/me" \
-H "Authorization: Bearer $ONIX_API_KEY"
{
"data": {
"user": {"id": 12, "name": "Budi Santoso", "email": "[email protected]", "avatar_url": null, "locale": "id", "timezone": null, "last_login_at": "2026-10-08T02:00:00Z"},
"via": "key",
"timezone": "Asia/Jakarta",
"workspace": {
"id": 3, "name": "Toko Budi", "slug": "toko-budi", "plan": "pro", "pro_until": "2026-11-08T03:15:00Z", "in_grace": false, "timezone": "Asia/Jakarta",
"limits": {"channels": 4, "users": 10, "tickets_per_month": 200, "replies_per_day": 0, "ai_per_month": 2000, "ai": true, "api": true},
"created_at": "2026-10-08T02:00:00Z"
},
"role": {"id": 1, "name": "Owner"},
"is_owner": true,
"is_platform_admin": false,
"permissions": ["dashboard.view", "interactions.view", "interactions.reply", "interactions.assign", "templates.manage", "channels.manage", "settings.members", "settings.roles", "settings.billing", "settings.audit", "settings.workspace", "settings.api"],
"channel_ids": null,
"realtime": true
}
}
Pada limits, nilai 0 berarti tanpa batas. channel_ids bernilai null berarti akses ke semua channel. timezone adalah zona efektif (zona pribadi pengguna, atau zona workspace).
Membalas pelanggan WhatsApp
Cari percakapan yang belum dibalas, lalu kirim balasan (butuh key ber-scope write). Pesan dikirim lewat nomor WhatsApp percakapan itu dan tercatat atas nama key.
curl -s "https://onix.sassly.ai/api/v1/interactions?tab=unreplied&per_page=5" \
-H "Authorization: Bearer $ONIX_API_KEY"
curl -s -X POST "https://onix.sassly.ai/api/v1/interactions/42/messages" \
-H "Authorization: Bearer $ONIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"text": "Halo kak, pesanan sudah kami kirim hari ini 🙏"}'
{
"data": {
"id": 981, "interaction_id": 42, "direction": "out", "type": "text", "body": "Halo kak, pesanan sudah kami kirim hari ini 🙏",
"media": null, "reply_to": null, "sender": {"name": "API · CRM", "user_id": 12, "jid": null},
"status": "sent", "error": null, "reactions": [], "sent_at": "2026-10-09T03:15:00Z", "created_at": "2026-10-09T03:15:00Z"
},
"meta": {"replies": {"used": 1, "limit": 0}}
}
Pesan yang ditolak WhatsApp tetap tersimpan dengan "status": "failed" dan alasan di error; kirim ulang lewat
/retry. Maksimal 30 pesan per menit per nomor (429 bila lewat).
Lampiran: kirim multipart/form-data dengan field file (maks. 16 MB).
Audit log anggota sejak awal bulan
curl -s "https://onix.sassly.ai/api/v1/audit-logs?category=anggota&from=2026-10-01&per_page=20" \
-H "Authorization: Bearer $ONIX_API_KEY"
{
"data": [
{
"id": 41, "action": "member.invited", "label": "Mengundang anggota", "category": "anggota", "icon": "user-plus",
"target": "[email protected]", "details": "Role: Agent",
"user": {"id": 12, "name": "Budi Santoso", "avatar_url": null},
"ip": "203.0.113.10", "created_at": "2026-10-08T03:20:00Z"
}
],
"meta": {"page": 1, "per_page": 20, "total": 1, "pages": 1, "categories": [{"key": "anggota", "label": "Anggota & undangan"}, "…"], "users": [{"id": 12, "name": "Budi Santoso"}]}
}
Contoh JavaScript (Node 18+) dan PHP
const res = await fetch("https://onix.sassly.ai/api/v1/members", {
headers: { Authorization: `Bearer ${process.env.ONIX_API_KEY}` },
});
const { data, error } = await res.json();
if (error) throw new Error(`${error.code}: ${error.message}`);
$ch = curl_init('https://onix.sassly.ai/api/v1/roles');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('ONIX_API_KEY')],
]);
$body = json_decode(curl_exec($ch), true);
Event real-time
Aplikasi menerima event lewat WebSocket (Centrifugo) di kanal ws:{workspace_id} dan user:{user_id}. Isi setiap event: {"event": "…", "data": {…}, "at": "…Z"}.
| Event | Kanal | Kapan |
|---|---|---|
notification.created | user:{id} | Notifikasi baru untuk pengguna. |
workspace.updated | ws:{id} | Nama workspace berubah. |
settings.updated | ws:{id} | Pengaturan General berubah (mis. zona waktu). |
members.changed | ws:{id} | Anggota/undangan berubah. |
teams.changed | ws:{id} | Tim atau anggota tim berubah. |
billing.updated | ws:{id} | Paket berubah (Pro aktif, turun ke Free, diatur admin). |
inbox.changed | ws:{id} | Ada perubahan di inbox: {"interaction_id", "channel_id", "reason"} tanpa isi pesan — muat ulang daftar lewat API (akses channel tetap dicek). |
channel.updated | ws:{id} | Status/pengaturan channel berubah, termasuk progres impor riwayat. |
labels.changed | ws:{id} | Label WhatsApp Business sebuah channel berubah. |
message.created / message.updated | conv:{id} | Pesan baru atau berubah (status kirim, reaksi, edit, tarik, media selesai diunduh). Isi = resource pesan. |
interaction.updated | conv:{id} | Status, penugasan, atau ringkasan percakapan berubah. |
typing | conv:{id} | Pelanggan (WhatsApp/livechat) atau agen lain sedang mengetik. |
visitor.online | conv:{id} | Pengunjung livechat sedang membuka widget (dikirim widget ±30 detik sekali). |
tickets.changed | ws:{id} | Tiket dibuat/berubah: {"ticket_id", "reason"} tanpa isi — muat ulang lewat API (hak lihat tetap dicek). |
ticket.message / ticket.message.updated | ticket:{id} | Pesan diskusi baru atau berubah (dikirim sebagai feedback). Isi = resource pesan tiket. |
ticket.event | ticket:{id} | Log tiket baru (status, prioritas, tenggat, peserta, feedback, kesimpulan). |
ticket.updated | ticket:{id} | Data tiket berubah — muat ulang detailnya. |
contacts.changed | ws:{id} | Kontak dibuat/diubah/digabung/dihapus/diimpor: {"contact_id", "reason"}. |
contacts.settings | ws:{id} | Label Onix atau field kustom berubah. |
kb.changed | ws:{id} | Kategori atau artikel knowledge base berubah, termasuk selesai/gagal diproses untuk pencarian makna: {"article_id"} atau {"category_id"}. |
pipeline.changed | ws:{id} | Lead, workflow, atau pengaturan Pipeline berubah: {"lead_id", "pipeline_id", "reason"} tanpa isi — muat ulang lewat API (kepemilikan data tetap dicek). |
clients.changed | ws:{id} | Klien dibuat/diubah/dihapus atau kontak ditautkan: {"client_id"}. |
broadcasts.changed | ws:{id} | Broadcast dibuat/diubah/dimulai/dijeda/selesai, progres kirim, atau tanda terima/balasan penerima: {"broadcast_id", "reason"} — muat ulang lewat API. |
segments.changed | ws:{id} | Segmen dibuat/diubah/dihapus: {"segment_id"}. |
Kanal conv:{id} hanya diberikan bila pengguna boleh melihat percakapan itu (akses channel + aturan tim). Saat percakapan di-assign ke tim/orang lain, yang kehilangan akses otomatis dicabut dari kanalnya.
Kanal ticket:{id} hanya diberikan bila pengguna boleh membuka tiket itu (peserta, anggota tim untuk tiket tanpa penanggung jawab, atau melihat semua data).
Widget livechat memakai kanal terpisah visitor:{sesi} (token dari POST /livechat/{key}/realtime) dengan event message, queue, typing, dan read — lihat Livechat.