Mobile or Access API Documentation

Dokumentasi REST API for Mobile or Access - SuperApp CSIS

Konfigurasi API

Realtime Events (Reverb / WebSocket)

Panduan listen private channel untuk update WhatsApp chat dan contact list secara realtime.

Route auth private channel web: /broadcasting/auth (middleware: web) untuk browser session + CSRF token. Untuk mobile gunakan: /api/mobile/v1/broadcasting/auth (middleware: auth:sanctum) dengan header Authorization: Bearer <token>.
Broadcaster
reverb
Auth Endpoint (Web)
/broadcasting/auth
Auth Endpoint (Mobile)
/api/mobile/v1/broadcasting/auth
Chat Channel
private-wa.chat.{contactId}
Contact Channel
private-wa.contacts.{clientId}
Channel Event Payload Ringkas
wa.chat.{contactId} .NewMessage { type: 'create|update', message: {...} }
wa.chat.{contactId} .NewComment { id, conversation_id, contact_id, comment, user, created_at, bubble_html }
wa.chat.{contactId} .ConversationAccountUpdated { conversation_id, contact_id, account_id, phone }
wa.contacts.{clientId} .ContactStateUpdated { contact_id, status, assigned_to }
wa.contacts.{clientId} .ContactPreviewUpdated { contact_id, preview, time }

Contoh Listen (Laravel Echo + Reverb)

window.Echo.private(`wa.chat.${contactId}`)
  .listen('.NewMessage', (payload) => console.log('NewMessage', payload))
  .listen('.NewComment', (payload) => console.log('NewComment', payload))
  .listen('.ConversationAccountUpdated', (payload) => console.log('ConversationAccountUpdated', payload));

window.Echo.private(`wa.contacts.${clientId}`)
  .listen('.ContactStateUpdated', (payload) => console.log('ContactStateUpdated', payload))
  .listen('.ContactPreviewUpdated', (payload) => console.log('ContactPreviewUpdated', payload));

Webchat API

Dua API terpisah untuk channel Webchat: Public Widget API (dipakai halaman chat anonim milik visitor) dan Agent Inbox API (dipakai aplikasi Webchat Beta oleh agent/manager/admin).

Kedua API Webchat ini bukan bagian dari /api/mobile/v1 dan tidak memakai Bearer token, jadi tidak muncul di tester "Test Endpoint" di bawah — dokumentasi di section ini murni referensi (contoh cURL/JS manual). Public Widget API tidak butuh autentikasi sama sekali (dibatasi lewat token widget + rate limit); Agent Inbox API butuh sesi login browser (cookie), bukan token yang bisa dipakai dari luar browser/Postman tanpa sesi tersebut.

1. Public Widget API (tanpa autentikasi)

Base Path
/api/webchat/{token}
Token
Token publik widget (lihat Manage Webchat Widgets)
Auth
Tidak ada — dibatasi honeypot field + rate limit
Rate Limit (umum)
30/menit per IP, 60/menit per widget token
Rate Limit (otp/request)
5/menit per IP, 3/10 menit per alamat email
Method Path Auth Tambahan Deskripsi
POST /check-history Cek apakah email/phone yang diketik sudah punya percakapan sebelumnya. Dipakai untuk menentukan apakah step OTP perlu ditampilkan (visitor baru = tidak perlu OTP sama sekali).
POST /otp/request Kirim kode OTP 6 digit ke email lewat email sender default milik client (fallback ke email account pertama jika tidak ada default). Kode berlaku 10 menit.
POST /otp/verify Verifikasi kode OTP. Maks 5x percobaan salah sebelum kode harus diminta ulang. Status verified tersimpan 30 menit dan sekali pakai (langsung terpakai habis saat /start berhasil).
POST /start Mulai atau lanjutkan sesi chat. Wajib sudah OTP-verified hanya jika email/phone ini sudah punya history webchat sebelumnya; visitor baru langsung lolos. Mengembalikan visitor_token yang disimpan visitor (localStorage) untuk semua request berikutnya.
GET /messages Header X-Visitor-Token Ambil seluruh pesan (lintas semua conversation, satu thread berkelanjutan) beserta data visitor (name/email/phone) untuk sesi yang sedang berjalan.
POST /messages Header X-Visitor-Token Kirim pesan teks dari visitor ke agent. Body: content (wajib, maks 4096 karakter).
POST /upload Header X-Visitor-Token Upload lampiran dari visitor. Multipart/form-data, field file (wajib, maks 20MB) — gambar/video/audio/dokumen otomatis dideteksi dari mime type.

Contoh: cek history → kirim OTP → verifikasi → mulai chat

TOKEN=nscs6iwivknjno4dsvouekhx3yyh32m9

# 1. Cek apakah email ini sudah punya history (menentukan perlu OTP atau tidak)
curl -X POST "https://apps.rndsolusi.com/api/webchat/$TOKEN/check-history" \
  -H "Content-Type: application/json" \
  --data '{"email":"budi@example.com","phone":"081234567890"}'
# -> {"success":true,"has_history":false}

# 2. Jika has_history=true, minta kode OTP dulu
curl -X POST "https://apps.rndsolusi.com/api/webchat/$TOKEN/otp/request" \
  -H "Content-Type: application/json" \
  --data '{"email":"budi@example.com","website":""}'
# -> {"success":true}

# 3. Verifikasi kode yang diterima lewat email
curl -X POST "https://apps.rndsolusi.com/api/webchat/$TOKEN/otp/verify" \
  -H "Content-Type: application/json" \
  --data '{"email":"budi@example.com","code":"123456"}'
# -> {"success":true}

# 4. Mulai sesi chat (name/email/phone; website = honeypot, kosongkan)
curl -X POST "https://apps.rndsolusi.com/api/webchat/$TOKEN/start" \
  -H "Content-Type: application/json" \
  --data '{"name":"Budi Santoso","email":"budi@example.com","phone":"081234567890","website":""}'
# -> {"success":true,"visitor_token":"...","conversation_id":123,"visitor_name":"Budi Santoso"}

# 5. Simpan visitor_token, lalu pakai untuk polling/kirim pesan
VISITOR_TOKEN="...dari langkah 4..."
curl "https://apps.rndsolusi.com/api/webchat/$TOKEN/messages" \
  -H "X-Visitor-Token: $VISITOR_TOKEN"

curl -X POST "https://apps.rndsolusi.com/api/webchat/$TOKEN/messages" \
  -H "Content-Type: application/json" \
  -H "X-Visitor-Token: $VISITOR_TOKEN" \
  --data '{"content":"Halo, saya butuh bantuan"}'

2. Agent Inbox API (Webchat Beta — sesi login browser)

Endpoint ini dipanggil oleh SPA Webchat Beta (/webchat-beta) memakai sesi cookie hasil login web biasa (role admin/manager/agent), bukan Bearer token — tidak bisa dites langsung dari cURL/Postman tanpa membawa cookie sesi tersebut. Semua endpoint menerima query client_id (hanya efektif untuk role admin memilih client lain; manager/agent selalu terikat ke client mereka sendiri).
Base Path
/webchat-beta/api
Auth
Sesi web (cookie) — middleware role:admin,manager,agent
Method Path Deskripsi
GET /contacts List + filter kontak webchat. Query: search, filter_status (open/closed/blacklisted), team_id, assigned_to, assigned_me, unassigned_only, tag_filter (Custom Inbox), sort, page. Response menyertakan open_count, unassigned_count, blacklisted_count, team_open_counts.
GET /contacts/{contact} Detail kontak: pesan halaman terbaru, timeline_items (pesan diselingi marker "Conversation opened/closed"), has_more_history, oldest_id.
GET /contacts/{contact}/history Pagination pesan lama (infinite scroll ke atas). Query: before_id, limit (default 30, maks 100).
PUT /contacts/{contact} Update panel Linked Contact. Body: name (wajib), email, address, notes, tags (array — tag protected seperti webchat-inbox otomatis dipertahankan).
POST /contacts/{contact}/send Kirim balasan agent. Body: content dan/atau file (multipart, maks 20MB) — minimal salah satu wajib diisi. Jika conversation aktif sudah closed, otomatis membuat conversation baru ter-assign ke agent yang membalas (history lama tetap sebagai riwayat).
POST /contacts/{contact}/assign Assign ke user (user_id — team ikut otomatis dari team user tsb) atau langsung ke team (team_id), atau kosongkan keduanya untuk unassign.
POST /contacts/{contact}/close Tutup percakapan. Body: category_id (wajib jika client punya master kategori), sub_category_id, summary (opsional).

Contoh (dari dalam sesi browser yang sudah login)

// Kirim balasan teks ke contact tertentu
fetch('/webchat-beta/api/contacts/123/send', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest' },
  credentials: 'same-origin',
  body: JSON.stringify({ client_id: 3, content: 'Halo, ada yang bisa dibantu?' })
});

// Tutup percakapan dengan kategori + ringkasan
fetch('/webchat-beta/api/contacts/123/close', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest' },
  credentials: 'same-origin',
  body: JSON.stringify({ client_id: 3, category_id: 1, sub_category_id: 2, summary: 'Sudah selesai dibantu' })
});

3. Realtime Events (Reverb / WebSocket)

Channel Tipe Event Payload Ringkas
webchat.chat.{contactId} Private (auth via /broadcasting/auth) .NewMessage { message: {...} } — dipakai Webchat Beta (agent)
webchat.widget.{visitorToken} Public (tanpa auth) NewMessage { message: {...} } — dipakai halaman widget visitor, di-key pakai visitor_token yang unguessable, bukan contact ID

Contoh Listen — Agent (Laravel Echo + Reverb)

window.Echo.private(`webchat.chat.${contactId}`)
  .listen('.NewMessage', (payload) => console.log('NewMessage', payload.message));

Contoh Listen — Visitor Widget (pusher-js langsung, tanpa Echo/auth)

const pusher = new Pusher(REVERB_APP_KEY, {
  wsHost: REVERB_HOST, wsPort: REVERB_PORT, wssPort: REVERB_PORT,
  forceTLS: true, enabledTransports: ['ws', 'wss'], disableStats: true,
});

pusher.subscribe(`webchat.widget.${visitorToken}`)
  .bind('NewMessage', (data) => console.log('NewMessage', data.message));