Langsung ke konten
WbizTool

API v2 (beta)

Webhook

Endpoint webhook adalah URL di server Anda yang dipanggil WbizTool saat terjadi sesuatu pada pesan: pesan terkirim, gagal, dibatalkan, atau kedaluwarsa. Anda langsung mendapat kabarnya tanpa polling, dan setiap request ditandatangani sehingga Anda dapat memastikan request itu berasal dari WbizTool.

OperasiEndpointScope
Menambahkan endpointPOST /api/v2/webhooksmessages:read
Daftar endpointGET /api/v2/webhooksmessages:read
Mengambil endpointGET /api/v2/webhooks/{id}messages:read
Menghapus endpointDELETE /api/v2/webhooks/{id}messages:read
Mengganti rahasia penandatangananPOST /api/v2/webhooks/{id}/rotate-secretmessages:read
Mengirim peristiwa ujiPOST /api/v2/webhooks/{id}/testmessages:read

Endpoint dimiliki oleh workspace dan menerima peristiwa untuk semua pesannya, apa pun yang mengirimnya: API, dashboard, kampanye, pengingat, atau integrasi. Karena itu kunci yang dibatasi ke sebagian nomor tidak dapat mengelolanya: setiap panggilan dijawab dengan 403 number_not_allowed.

Peristiwa#

JenisKapan
message.sentPesan terkirim dari nomor Anda.
message.failedPesan tidak dapat dikirim; error.message menyebutkan alasannya.
message.cancelledPesan yang menunggu dibatalkan: dengan API, dari dashboard, atau karena nomor atau kampanyenya dihapus.
message.expiredPesan tidak terkirim sebelum expires_at-nya.
pingPeristiwa uji yang Anda minta.

Peristiwa untuk nomor (terhubung, ter-logout) dan untuk pesan masuk akan menyusul. Centang terkirim dan dibaca tidak mengirim peristiwa; ambil pesannya untuk melihatnya.

Menambahkan endpoint#

POSThttps://wbiztool.com/api/v2/webhooks

Body: JSON (application/json)

Body

urlstringwajib

Endpoint Anda: alamat https:// publik, hingga 500 karakter. Alamat http://, privat, dan lokal (seperti localhost atau 192.168.x.x) ditolak.

eventsarray of stringsopsional

Jenis peristiwa yang diterimanya: salah satu atau beberapa dari message.sent, message.failed, message.cancelled, dan message.expired. Default: keempatnya. ping selalu datang saat Anda memintanya.

descriptionstringopsional

Catatan untuk Anda sendiri, hingga 100 karakter, seperti Order system.

Satu workspace dapat memiliki hingga 5 endpoint. Responsnya 201 dengan endpoint beserta secret penandatanganannya, yang hanya ditampilkan kali ini. Simpan di tempat yang dapat dibaca penerima Anda, seperti environment variable. Respons berikutnya hanya menampilkan secret_last4; jika rahasianya hilang, ganti rahasianya.

curl -X POST https://wbiztool.com/api/v2/webhooks \
  -H "Authorization: Bearer $WBIZTOOL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/wbiztool/events",
    "events": ["message.sent", "message.failed"],
    "description": "Order system"
  }'

Respons (201):

{
  "id": 41,
  "url": "https://example.com/wbiztool/events",
  "description": "Order system",
  "events": ["message.sent", "message.failed"],
  "secret_last4": "9c1e",
  "active": true,
  "disabled_reason": null,
  "created_at": "2026-10-18T11:20:05.733Z",
  "last_delivery": null,
  "secret": "3f0b…9c1e"
}

secret yang sebenarnya terdiri dari 64 karakter heksadesimal. Percobaan ulang request ini dengan Idempotency-Key yang sama tidak menambahkan endpoint kedua, dan responsnya tidak menyertakan rahasia.

Error saat menambahkan endpoint#

HTTPKodeKapan
400validation_failedurl tidak ada atau terlalu panjang, events kosong atau berisi jenis yang tidak dikenal, atau ada field yang tidak dikenal
403webhook_limit_reachedWorkspace sudah memiliki 5 endpoint
403number_not_allowedKunci dibatasi ke sebagian nomor
422invalid_webhook_urlurl bukan alamat https:// publik

Daftar endpoint#

GEThttps://wbiztool.com/api/v2/webhooks

Endpoint workspace yang menerima peristiwa, yang terlama lebih dulu, dalam satu daftar data.

curl https://wbiztool.com/api/v2/webhooks \
  -H "Authorization: Bearer $WBIZTOOL_API_KEY"

Daftar ini tidak menyertakan endpoint yang sudah berhenti. Pemilik juga dapat melihat endpoint, dan menghapusnya, di Pengaturan → Kunci API pada bagian Endpoint webhook.

Mengambil endpoint#

GEThttps://wbiztool.com/api/v2/webhooks/{id}

Satu endpoint. last_delivery menunjukkan hasil pengiriman terakhirnya. Endpoint yang tidak ada atau sudah dihapus dijawab dengan 404 webhook_not_found; endpoint yang sudah berhenti ditampilkan dengan active: false.

Menghapus endpoint#

DELETEhttps://wbiztool.com/api/v2/webhooks/{id}

Tidak ada lagi yang dikirim ke endpoint itu, termasuk percobaan ulang yang masih menunggu. Responsnya {"id": 41, "deleted": true}.

Mengganti rahasia penandatanganan#

POSThttps://wbiztool.com/api/v2/webhooks/{id}/rotate-secret

Membuat rahasia baru untuk endpoint. Responsnya 200 dengan endpoint beserta secret barunya, yang hanya ditampilkan kali ini. Rahasia lama langsung berhenti berlaku: peristiwa yang dikirim setelah ini ditandatangani dengan rahasia baru, termasuk percobaan ulang peristiwa sebelumnya. Segera perbarui penerima Anda.

curl -X POST https://wbiztool.com/api/v2/webhooks/41/rotate-secret \
  -H "Authorization: Bearer $WBIZTOOL_API_KEY"

Mengirim peristiwa uji#

POSThttps://wbiztool.com/api/v2/webhooks/{id}/test

Memasukkan peristiwa ping ke antrean untuk endpoint ini, ditandatangani seperti setiap peristiwa, sehingga Anda dapat menguji penerima Anda. Responsnya 202:

{ "event_id": "evt_8a2f4c1d9b7e6a5f4c3b2a19", "type": "ping", "queued": true }

Endpoint Anda menerima:

{
  "id": "evt_8a2f4c1d9b7e6a5f4c3b2a19",
  "type": "ping",
  "created_at": "2026-10-18T11:21:40.002Z",
  "data": { "webhook_id": 41 }
}

Payload peristiwa#

Setiap peristiwa berupa POST dengan body JSON:

{
  "id": "evt_c41d7e2a9f3b8c6d5e4f3a21",
  "type": "message.sent",
  "created_at": "2026-10-18T10:15:09.912Z",
  "data": {
    "message": {
      "id": 9817263,
      "status": "sent",
      "from": { "id": 101, "phone": "919800000000", "platform": "whatsapp" },
      "to": { "phone": "+919876543210", "contact_id": 991 },
      "text": "Hi Asha, your order #1042 is ready.",
      "media": null,
      "send_at": null,
      "expires_at": null,
      "created_at": "2026-10-18T10:15:02.311Z",
      "sent_at": "2026-10-18T10:15:09.870Z",
      "error": null
    }
  }
}
FieldKeterangan
idID peristiwa, evt_ diikuti 24 karakter. Peristiwa yang sama mempertahankan ID-nya di setiap percobaan ulang.
typeSalah satu jenis peristiwa.
created_atKapan peristiwa terjadi.
data.messageUntuk peristiwa message.*: Message sebagaimana kondisinya saat itu. media.url di dalamnya berfungsi setidaknya selama 26 jam.
data.webhook_idUntuk ping: ID endpoint.

Header:

HeaderNilai
Content-Typeapplication/json
User-AgentWbizTool-Webhooks/2
WbizTool-Event-Idid peristiwa, sama di setiap percobaan ulang
WbizTool-TimestampKapan percobaan ini dikirim, dalam detik Unix, seperti 1792310409
WbizTool-Signaturev1= diikuti HMAC-SHA256 heksadesimal dari <timestamp>.<raw body>, dibuat dengan rahasia endpoint

Memverifikasi tanda tangan#

Periksa setiap request sebelum Anda memercayainya: hitung tanda tangan dari body mentah (sebelum framework Anda mengurai JSON-nya), bandingkan dengan header dalam waktu konstan, dan tolak timestamp yang selisihnya lebih dari 5 menit, agar request lama tidak dapat diputar ulang. Skemanya sama dengan tanda tangan webhook API v1, dengan rahasia milik endpoint itu sendiri.

Lalu gunakan WbizTool-Event-Id untuk membuang duplikat: peristiwa yang sama dapat datang lebih dari sekali, misalnya saat respons Anda hilang dan kami mencoba lagi.

import hashlib, hmac, json, os, time

SECRET = os.environ["WBIZTOOL_WEBHOOK_SECRET"]

def verify(secret: str, body: bytes, headers) -> bool:
    ts, sig = headers.get("WbizTool-Timestamp", ""), headers.get("WbizTool-Signature", "")
    if not ts.isdigit() or abs(time.time() - int(ts)) > 300:
        return False
    mac = "v1=" + hmac.new(secret.encode(), ts.encode() + b"." + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(mac, sig)

# Flask
from flask import Flask, request

app = Flask(__name__)
seen = set()  # use your database in production

@app.post("/wbiztool/events")
def events():
    body = request.get_data()  # the raw bytes
    if not verify(SECRET, body, request.headers):
        return "", 401
    event_id = request.headers["WbizTool-Event-Id"]
    if event_id in seen:
        return "", 200  # a repeat: already handled
    seen.add(event_id)
    event = json.loads(body)
    if event["type"] == "message.failed":
        message = event["data"]["message"]
        print("Failed:", message["id"], message["error"]["message"])
    return "", 200

Di Django, berikan request.body dan request.headers.

Jawab 2xx dengan cepat, lalu kerjakan proses yang lambat setelahnya (misalnya di antrean).

Percobaan ulang#

  • Jawab dengan 2xx apa pun dalam 10 detik. Selain itu dianggap gagal: kode status lain (termasuk 4xx), tidak ada jawaban dalam 10 detik, atau tidak ada koneksi dalam 3 detik. Redirect diikuti, paling banyak 3 kali, dan masing-masing harus mengarah ke alamat publik.
  • Pengiriman yang gagal dicoba lagi setelah 1, 5, dan 15 menit, lalu 1, 2, 4, 8, dan 8 jam: 9 percobaan dalam sekitar 23 jam. Setelah percobaan terakhir, peristiwa itu dibuang.
  • Percobaan ulang memiliki body dan WbizTool-Event-Id yang sama, dengan WbizTool-Timestamp dan tanda tangan yang baru.
  • Urutan tidak dijamin. message.sent yang dicoba ulang dapat datang setelah peristiwa yang lebih baru. Gunakan status pesan, atau ambil pesannya, jika urutan penting.

last_delivery pada endpoint menunjukkan hasil pengiriman terakhir: state (pending, delivered, atau failed), status_code yang dijawab server Anda, dan kapan peristiwa dibuat.

Kapan endpoint berhenti#

Endpoint berhenti menerima peristiwa jika salah satu hal berikut terjadi. Endpoint tetap ada di GET /webhooks dengan active: false dan disabled_reason, sehingga Anda dapat melihat alasannya; endpoint masih dapat dibaca dan dihapus, tetapi tidak dapat diuji atau diberi rahasia baru (404).

  • Gagal selama 24 jam. Jika tidak ada yang berhasil dikirim ke endpoint itu selama 24 jam sementara pengirimannya terus gagal, endpoint dinonaktifkan dan percobaan ulang yang menunggu dibuang. Pengaturan → Kunci API kemudian menampilkannya sebagai Nonaktif. Perbaiki server Anda, lalu tambahkan endpoint lagi.
  • Kunci yang membuatnya dicabut atau kedaluwarsa. Mencabut kunci menghentikan semua yang disiapkannya. Tambahkan endpoint lagi dengan kunci lain.
  • Endpoint dihapus, dengan Menghapus endpoint atau di Pengaturan → Kunci API.

Endpoint yang sudah berhenti tidak dihitung dalam batas 5.

Objek endpoint webhook#

FieldJenisKeterangan
idintegerID endpoint.
urlstringTujuan pengiriman peristiwa.
descriptionstringCatatan Anda; "" jika tidak ada.
eventsarrayJenis peristiwa yang diterimanya.
secretstringRahasia penandatanganan: hanya ada di respons Menambahkan endpoint dan Mengganti rahasia penandatanganan.
secret_last4string4 karakter terakhir rahasia, untuk mengetahui rahasia mana yang Anda miliki.
activebooleanfalse jika endpoint tidak lagi menerima peristiwa – lihat Kapan endpoint berhenti.
disabled_reasonstring or nullAlasan berhenti (gagal selama 24 jam, atau kunci yang membuatnya dicabut atau kedaluwarsa); null selama aktif.
created_atstringKapan endpoint ditambahkan.
last_deliveryobject or nullPengiriman terakhir yang dicoba: state, status_code (atau null jika server Anda tidak menjawab), dan created_at. null sebelum pengiriman pertama.

Terkait#