Lewati ke konten

Setup webhook

Daftarkan URL webhook di dashboard dan siapkan server yang menerima event dari CSKU.

Webhook membuat CSKU mengirim POST ke server Anda setiap kali ada pesan masuk dari pelanggan, balasan AI, atau balasan agen. Anda tidak perlu polling ke Ambil pesan.

Prasyarat

  • Paket Anda punya fitur Webhook. Jika tidak, menu Webhook menampilkan ajakan upgrade. Lihat Berlangganan & kredit.
  • Anda login sebagai owner bisnis. OTP hanya dikirim ke email owner.
  • Secret Key sudah dibuat di Pengaturan → Secret Key. Nilai ini dikirim di header Authorization setiap request webhook. Lihat Autentikasi.
  • Server Anda bisa diakses publik lewat https. Dashboard menolak URL http, localhost, dan alamat IP privat.

Daftarkan URL

  1. Buka Pengaturan → Webhook.
  2. Isi Webhook URL, misalnya https://api.toko-anda.com/csku/webhook.
  3. Klik Perbarui Webhook, lalu konfirmasi. CSKU mengirim kode OTP 6 digit ke email owner. Kode berlaku 5 menit.
  4. Masukkan kode OTP, lalu klik Perbarui Webhook.

Setelah tersimpan, semua event langsung dikirim ke URL tersebut.

Satu URL, semua event

Setiap bisnis punya satu URL webhook. Semua event dikirim ke URL itu dan tidak bisa difilter dari dashboard. Abaikan event yang tidak Anda perlukan di server Anda. Daftar event ada di Event & payload.

Contoh penerima

Server Anda wajib:

  1. Mencocokkan header Authorization dengan Secret Key Anda.
  2. Membalas body JSON {"success": true} secepatnya (di bawah 30 detik).

Status HTTP tidak dibaca. Yang menentukan sukses hanya field success di body. Detail ada di Keamanan & retry.

Node.js (Express)

JavaScript
import express from 'express'
import crypto from 'node:crypto'

const app = express()
app.use(express.json())

const SECRET = process.env.CSKU_SECRET

function isValid(header) {
  const a = Buffer.from(header || '')
  const b = Buffer.from(SECRET)
  return a.length === b.length && crypto.timingSafeEqual(a, b)
}

app.post('/csku/webhook', (req, res) => {
  if (!isValid(req.get('Authorization'))) {
    return res.status(401).json({ success: false })
  }

  res.json({ success: true })

  // Proses setelah membalas
  const { event, message } = req.body
  console.log(event, message.id)
})

app.listen(3000)

PHP

PHP
<?php
$secret = getenv('CSKU_SECRET');
$auth = $_SERVER['HTTP_AUTHORIZATION'] ?? '';

header('Content-Type: application/json');

if (!hash_equals($secret, $auth)) {
    http_response_code(401);
    echo json_encode(['success' => false]);
    exit;
}

$payload = json_decode(file_get_contents('php://input'), true);

// Simpan ke antrean, lalu balas
echo json_encode(['success' => true]);

Header Authorization di Apache

Beberapa konfigurasi Apache + PHP-FPM tidak meneruskan header Authorization. Jika $_SERVER['HTTP_AUTHORIZATION'] kosong, tambahkan SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 di .htaccess.

Python (Flask)

Python
import hmac
import os
from flask import Flask, request, jsonify

app = Flask(__name__)
SECRET = os.environ["CSKU_SECRET"]

@app.post("/csku/webhook")
def csku_webhook():
    auth = request.headers.get("Authorization", "")
    if not hmac.compare_digest(auth, SECRET):
        return jsonify(success=False), 401

    payload = request.get_json(silent=True) or {}
    # Kirim ke antrean / background job
    print(payload.get("event"), payload.get("message", {}).get("id"))

    return jsonify(success=True)

Go

Go
package main

import (
    "crypto/subtle"
    "encoding/json"
    "net/http"
    "os"
)

var secret = []byte(os.Getenv("CSKU_SECRET"))

func webhook(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")

    auth := []byte(r.Header.Get("Authorization"))
    if subtle.ConstantTimeCompare(auth, secret) != 1 {
        w.WriteHeader(http.StatusUnauthorized)
        w.Write([]byte(`{"success":false}`))
        return
    }

    var payload map[string]any
    if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
        w.Write([]byte(`{"success":false}`))
        return
    }

    // Proses di goroutine / antrean
    w.Write([]byte(`{"success":true}`))
}

func main() {
    http.HandleFunc("/csku/webhook", webhook)
    http.ListenAndServe(":3000", nil)
}

Uji saat development

Belum ada tombol "kirim webhook uji". Untuk mencoba:

  1. Pakai URL publik sementara:
    • webhook.site untuk melihat isi request tanpa menulis kode. Ingat: webhook.site tidak membalas {"success": true} secara default, jadi CSKU akan mencoba ulang.
    • Tunnel ke server lokal, misalnya ngrok http 3000 atau cloudflared tunnel --url http://localhost:3000. Daftarkan URL https yang diberikan tunnel.
  2. Picu event sungguhan: kirim pesan ke salah satu channel Anda (misalnya lewat Webchat atau WhatsApp). Anda akan menerima channel.message_in, lalu ai.message_generated jika AI agent aktif.
  3. Balas dari menu Chat di dashboard untuk menerima agent.message_out.

Ganti URL setelah selesai

URL tunnel biasanya berubah setiap kali dijalankan ulang. Daftarkan URL produksi sebelum go-live, agar event tidak terkirim ke alamat yang sudah mati.

Reset webhook

Buka Pengaturan → Webhook, klik Reset, lalu konfirmasi. URL dihapus dan CSKU berhenti mengirim event. Untuk mengaktifkan lagi, daftarkan URL baru dengan OTP.

Selanjutnya