Daftar isi panduan

Webhook: kirim pesanan baru dan tiket baru ke sistem kamu

Tiap ada pesanan atau tiket baru, QwikChat ngirim datanya ke CRM, sheet, atau aplikasi kamu sendiri — ditandatangani dan dicoba ulang kalau gagal.

Webhook itu cara QwikChat ngabarin sistem kamu sendiri — Google Sheet lewat Zapier/Make, CRM, aplikasi gudang, bot Slack — begitu sesuatu kejadian. QwikChat ngirim satu request POST berisi JSON ke alamat yang kamu tentuin, ditandatangani pakai kunci rahasia, dan dicoba ulang sendiri kalau server kamu lagi gak bisa dihubungi.

Kejadian yang bisa dikirim

order.created — pesanan baru tercatat. Dikirim begitu obrolan pertama kali menghasilkan pesanan, sebelum pelanggan bilang "ya". Isinya masih draf: barang, jumlah, dan alamatnya masih bisa berubah, dan bisa aja gak pernah dikonfirmasi.

order.confirmed — pesanan dikonfirmasi pelanggan. Ini pesanan yang beneran harus diproses. Kalau kamu cuma butuh satu webhook buat pesanan, pakai yang ini.

ticket.created — tiket baru dibuka. Baik yang dicatat AI dari keluhan pelanggan, maupun yang dicatat tim lewat tombol Catat sebagai tiket di Kotak Masuk.

Di daftar yang sama juga ada escalation (percakapan yang diserahkan ke orang tapi kelamaan belum diambil) dan jenis-jenis pesan hasil bacaan AI seperti complaint atau check_status. Halaman ini fokus ke tiga yang di atas.

Pasang webhook: lewat Rute webhook

order.created dan ticket.created cuma dikirim lewat rute. Tanpa rute yang aktif, dua kejadian ini gak dikirim ke mana-mana — juga gak ke URL di Webhook pesanan, karena alamat itu khusus buat pesanan yang udah dikonfirmasi.

  1. Buka halaman Rute webhook

    Dari menu akun, buka Semua workspace, pilih workspace kamu, lalu Webhook pesanan. Tekan Lihat log pengiriman, terus tombol Rute webhook di kanan atas.

  2. Pilih perangkatnya

    Rute itu milik satu perangkat. Pilih perangkatnya di pojok kanan atas. Punya beberapa perangkat (misalnya WhatsApp dan chat website)? Pasang rutenya di tiap perangkat yang mau kamu pantau.

  3. Tekan + Tambah rute, isi formnya

    Kejadian: pilih order.created atau ticket.created. URL tujuan: alamat penerima kamu, yang bisa diakses dari internet. Pakai https:// — isi pesanan dan data pelanggan ikut dikirim, dan http:// biasa ngirimnya tanpa enkripsi. Nama boleh diisi biar gampang dikenali, misalnya "CRM" atau "Sheet tiket".

    Kunci penanda tangan: isi dengan kunci rahasia buatan kamu sendiri (minimal 32 karakter acak). Kalau dikosongin, dipakai kunci perangkat — yang muncul di halaman Webhook pesanan setelah URL webhook pesanan diisi. Satu kunci per rute lebih aman: kalau satu bocor, yang lain gak ikut.

    Transform dan Ambang keyakinan biarin kosong dulu. Ambang keyakinan cuma berlaku buat jenis pesan hasil bacaan AI, gak buat kejadian di halaman ini.

  4. Centang Aktif, lalu Tambah rute

    Mulai saat itu tiap pesanan atau tiket baru di perangkat itu dikirim ke URL kamu. Satu kejadian boleh punya beberapa rute — semuanya dikirimi.

Isi order.created

Bentuknya sama persis kayak order.confirmed, jadi penerima kamu bisa pakai satu kode buat dua-duanya. Bedanya cuma dua: event-nya, dan ada created_at (waktu pesanan tercatat) sebagai ganti confirmed_at.

{
  "event": "order.created",
  "order_id": "8b0d6a52-3f1e-4c3a-9a51-2f6f0c1d7e44",
  "bot_id": "1c9e7f20-5b8a-4d2e-8f61-0a3b4c5d6e7f",
  "conversation_id": "d4e5f6a7-b8c9-4d0e-9f1a-2b3c4d5e6f70",
  "status": "draft",
  "lines": [
    {
      "sku": "KPI-250",
      "name": "Kopi Arabika 250 g",
      "qty": 2,
      "unit_price": 85000,
      "line_total": 170000
    }
  ],
  "subtotal": 170000,
  "shipping": 0,
  "discount": 0,
  "total": 170000,
  "dp_percent": 0,
  "dp": 0,
  "remaining": 170000,
  "address": "",
  "note": "",
  "confidence": 100,
  "template": "instant_purchase",
  "currency": "IDR",
  "created_at": "2026-10-27T03:15:42Z"
}

Semua nominal dalam rupiah, bilangan bulat (tanpa desimal). status di kejadian ini selalu draft. coupon_code cuma ada kalau pelanggan pakai kupon, dan fields cuma ada kalau pesanannya pakai bentuk lain selain beli langsung — misalnya tanggal buat booking.

Isi ticket.created

{
  "event": "ticket.created",
  "ticket_id": "5a7c2e19-0d4b-4f8a-b6e3-91c2d8f4a0b5",
  "number": 1042,
  "store_id": "7e3f9a10-2c4d-4b6e-8a1f-3d5c7b9e0a24",
  "bot_id": "1c9e7f20-5b8a-4d2e-8f61-0a3b4c5d6e7f",
  "conversation_id": "d4e5f6a7-b8c9-4d0e-9f1a-2b3c4d5e6f70",
  "customer": "6281234567890",
  "subject": "Tidak bisa login ke aplikasi",
  "message": "Min, dari tadi saya gak bisa login, katanya password salah terus",
  "category": "technical",
  "priority": "normal",
  "status": "open",
  "source": "ai",
  "ai_intent": "technical_issue",
  "ai_confidence": 88,
  "first_response_due_at": "2026-10-27T07:15:42Z",
  "resolution_due_at": "2026-10-28T03:15:42Z",
  "created_at": "2026-10-27T03:15:42Z"
}

number nomor tiket yang kelihatan di aplikasi (#1042). customer identitas pelanggan: nomor WhatsApp, username Telegram, atau kode pengunjung buat chat website. message pesan pelanggan yang bikin tiket ini dibuka.

category: complaint, technical, billing, return_refund, order_issue, atau other. priority: low, normal, high, atau urgent. source: ai kalau dicatat bot, manual kalau dicatat tim.

Beberapa kunci boleh gak ada. ai_intent dan ai_confidence cuma di tiket dari AI. assigned_team cuma ada kalau tiketnya langsung masuk antrean tim. first_response_due_at dan resolution_due_at (target SLA, dalam UTC) gak ada kalau target buat prioritas itu dikosongin di Pengaturan SLA.

Header dan tanda tangan

Tiap request bawa header ini:

Content-Type: application/json
X-QwikChat-Event: ticket.created
X-QwikChat-Idempotency-Key: ticket.created:1042:5a7c2e19-0d4b-4f8a-b6e3-91c2d8f4a0b5
X-QwikChat-Signature: t=1761534942,v1=3f9c0b…e81a
X-QwikChat-Transform: 

X-QwikChat-Signature buktiin kalau request-nya beneran dari QwikChat. Cara ngeceknya: gabungin angka t, titik, dan isi request mentah; hitung HMAC-SHA256-nya pakai kunci penanda tangan; hasilnya (hex) harus sama dengan v1. Contoh di Node.js:

const crypto = require('crypto');

// rawBody: isi request PERSIS seperti yang diterima (Buffer),
// sebelum di-parse jadi JSON. Jangan JSON.stringify ulang.
function verifyQwikChat(rawBody, signatureHeader, secret) {
  const parts = Object.fromEntries(
    signatureHeader.split(',').map((p) => p.split('='))
  );
  const t = Number(parts.t);
  // Tolak yang umurnya lebih dari 5 menit (mencegah kiriman diputar ulang).
  if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false;

  const expected = crypto
    .createHmac('sha256', secret)
    .update(t + '.')
    .update(rawBody)
    .digest('hex');

  const a = Buffer.from(expected);
  const b = Buffer.from(parts.v1 || '');
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Jawaban server kamu, dan percobaan ulang

Balas dengan status 2xx (misalnya 200) secepatnya — kerjain prosesnya belakangan kalau lama. QwikChat nunggu paling lama 10 detik.

Kalau gagal — timeout, server mati, atau status 429 dan 5xx — QwikChat nyoba lagi sendiri: 1 menit, 2 menit, 4 menit, 8 menit, lalu 16 menit kemudian, jadi 6 percobaan dalam sekitar setengah jam. Status 4xx lainnya (misalnya 400, 401, 404) dianggap ditolak dan gak dicoba lagi.

Yang tetap gagal masuk ke Gagal (DLQ) di halaman log pengiriman. Setelah server kamu beres, tekan Kirim ulang di barisnya.

Tiket: catat masalah pelanggan, kerjakan, dan kejar target waktunya Katalog produk dan hitung pesanan Semua yang bisa dikerjakan bot: jualan dan layanan pelanggan

Pertanyaan yang sering muncul

Udah ngisi URL di Webhook pesanan, kok pesanan baru dan tiket gak dikirim?

URL di Webhook pesanan cuma nerima pesanan yang udah dikonfirmasi (order.confirmed). Pesanan baru dan tiket butuh rute sendiri di Rute webhook — boleh ke URL yang sama.

Satu pesanan bisa dikirim berapa kali?

order.created sekali, pas pesanannya pertama kali tercatat. Perubahan isi pesanan setelahnya gak dikirim ulang. Kalau pelanggan konfirmasi, giliran order.confirmed yang dikirim, juga sekali.

Pesanan yang dibatalin sebelum dikonfirmasi gimana?

Gak ada kabar susulan. Makanya order.created jangan dipakai buat motong stok: anggap aja itu calon pesanan.

Tiket yang dicatat tim lewat Kotak Masuk ikut dikirim?

Ikut. Semua tiket baru dikirim, apa pun asalnya; bedanya kelihatan di kunci source (ai atau manual).

Server saya di jaringan kantor (localhost / IP lokal). Bisa?

Gak bisa — demi keamanan, QwikChat gak mau ngirim ke alamat jaringan lokal. Pakai alamat yang bisa diakses dari internet, misalnya lewat layanan seperti Zapier, Make, atau tunnel.