Pantau status pengiriman biar kamu tahu pesan kekirim atau nggak, pelanggan beneran baca (read receipt), dan kalau ada yang gagal kamu bisa deteksi langsung.
Wazapin kirim update status ini ke endpoint HTTPS kamu lewat event message.status_update.
Alur perubahan status
Pesan keluar lewat status berikut:
stateDiagram-v2
[*] --> queued: Request API
queued --> sent: Diteruskan ke Meta
sent --> delivered: Sampai di HP
delivered --> read: Dibuka user
queued --> failed: Error validasi / Meta
sent --> failed: Error pengiriman Metaqueued: Pesan sudah masuk antrean Wazapin. (Langsung dibalikin samaPOST /v1/messages).sent: Meta/WhatsApp sudah terima pesannya.delivered: Pesan sudah sampai di HP penerima (centang dua di WhatsApp).read: User sudah buka pesannya (centang dua biru).failed: Pesan gagal kekirim.
Struktur payload webhook
Beda sama webhook pesan masuk, payload message.status_update sudah bawa status terbaru langsung di body webhook. Kamu nggak perlu panggil GET /v1/messages/{messageID} cuma buat ambil statusnya.
Contoh payload-nya:
{
"message_id": "9f1fd66d-c37a-4b50-a8c2-b4dca523f9c8",
"conversation_id": "0f89b0f9-74b4-44f9-b9b6-48f6d4de57aa",
"status": "delivered",
"organization_id": "org_123"
}Contoh kode
Cara tangkap webhook dan proses perubahan statusnya:
# Kalau kamu ketinggalan webhook, cek status lewat API:
curl -X GET "https://api.wazapin.com/v1/messages/9f1fd66d-c37a-4b50-a8c2-b4dca523f9c8/status" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Accept: application/json"import express from "express";
import { Webhook } from "svix";
const app = express();
const wh = new Webhook(process.env.WAZAPIN_WEBHOOK_SECRET!);
app.post("/webhooks/wazapin", express.raw({ type: "application/json" }), async (req, res) => {
try {
wh.verify(req.body, req.headers as Record<string, string>);
} catch (err) {
return res.status(403).send("Invalid signature");
}
const payload = JSON.parse(req.body.toString("utf8"));
// Cek event update status
// Beberapa payload map nama event di luar, atau filter per endpoint
if (payload.status && payload.message_id) {
const messageId = payload.message_id;
const currentStatus = payload.status; // sent, delivered, read, failed
console.log(`Message ${messageId} updated to: ${currentStatus}`);
// Update status di database kamu di sini...
// db.messages.update({ where: { id: messageId }, data: { status: currentStatus } });
if (currentStatus === "failed") {
// Handle kalau gagal kekirim (mis. cek error code)
console.error(`Message ${messageId} failed to deliver.`);
}
}
res.status(200).send("OK");
});from fastapi import FastAPI, Request, HTTPException
from svix.webhooks import Webhook, WebhookVerificationError
import os
app = FastAPI()
wh = Webhook(os.environ["WAZAPIN_WEBHOOK_SECRET"])
@app.post("/webhooks/wazapin")
async def handle_webhook(request: Request):
body = await request.body()
try:
wh.verify(body, dict(request.headers))
except WebhookVerificationError:
raise HTTPException(status_code=403, detail="Invalid signature")
payload = await request.json()
status = payload.get("status")
message_id = payload.get("message_id")
if status and message_id:
print(f"Message {message_id} status updated to: {status}")
# Update data di database kamu di sini
# db.update_message_status(message_id, status)
if status == "failed":
print(f"Message {message_id} failed to deliver.")
return {"ok": True}Polling fallback
Kalau webhook receiver kamu sempat offline atau kamu kelewat webhook update status, kamu bisa tanya langsung ke API sebagai cadangan.
Wazapin sediain dua endpoint buat cek status:
- GET /v1/messages/{messageID}: Ambil data pesan lengkap termasuk
statusterbaru. - GET /v1/messages/{messageID}/status: Endpoint ringan yang cuma balikin metadata status.
Troubleshooting
Update status datang nggak urut
Karena konkurensi jaringan, webhook read kadang bisa datang duluan sebelum delivered.
- Selalu cek status yang sudah kesimpan di database kamu sebelum update.
- Jangan timpa status akhir kayak
readataufaileddengan status yang lebih awal kayaksentataudelivered.
Handle kalau gagal
Kalau status pesan jadi failed, ambil detail lengkapnya pakai GET /v1/messages/{messageID}. Response-nya bakal kasih blok error kayak error_code atau failure_reason yang jelasin kenapa gagal kekirim. Cek Referensi kode error buat detailnya.