Order Webhooks
Receive order result callbacks and verify the webhook signature.
Modified at Apr 28, 2026, 05:38 AM UTC
Cek Ceir sends order webhooks when an order is created through an API key that has a webhook URL configured.
Destination Rules
Webhook URLs must use HTTPS and be publicly reachable. Localhost, private IP ranges, loopback addresses, and URLs with embedded username or password are rejected.
POSTyour webhook URL
Cek Ceir sends a POST request with a JSON body to your configured webhook URL.
Content-Type: application/jsonAccept: application/json, text/plain, */*X-Webhook-Event: dispatch.webhook.orderX-Signature: <hex hmac sha256>Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
| Content-Type | header string | Yes | Always application/json. |
| Accept | header string | Yes | Accepted response formats sent by the webhook sender. |
| X-Webhook-Event | header string | Yes | Webhook event name, currently dispatch.webhook.order. |
| X-Signature | header string | Yes | HMAC SHA-256 signature for the order payload. |
| status | body string | Yes | Order processing result. |
| order_id | body number | Yes | Order ID. |
| transaction_id | body number | Yes | Wallet transaction ID. |
| service_code | body string | Yes | Service code. |
| charged_amount | body number | Yes | Amount captured from the wallet. |
| total_price | body number | Yes | Total order price before capture/refund adjustment. |
The body is the order placement payload:
Payload Example
{ "status": "success", "reference_id": "provider-reference-123", "message": "Pesanan-mu telah berhasil kami proses.", "processed": 1, "processed_success": 1, "processed_error": 0, "remaining_balance": 98500, "result": { "status": "registered" }, "error_message": null, "order_id": 321, "transaction_id": 654, "service_code": "cek_imei", "total": 1, "price": 1500, "total_price": 1500, "charged_amount": 1500, "refunded_amount": 0, "balance_before": 100000, "created_at": "2026-04-26T00:00:00.000Z"}Response
Return any 2xx response to acknowledge delivery.
{ "ok": true}Response Fields
| Field | Type | Required | Description |
|---|---|---|---|
| ok | boolean | No | Optional acknowledgement flag from your webhook handler. |
Verify Signature
The signature is:
HMAC_SHA256(JSON.stringify({ orderId, amount }), api_key_secret)Use only the secret part of the API key as the HMAC key. amount is signed as a string. Do not convert it to a floating point number.
The signed amount follows the webhook event generated by the application:
| Payload status | Signed amount |
|---|---|
| pending | String(total_price) |
| failed or cancelled | "0" |
| success, partial, or completed | String(charged_amount) |
import crypto from "node:crypto";import express from "express";const app = express();app.use(express.json());app.post("/webhooks/order", (req, res) => { const secret = process.env.API_KEY_SECRET ?? ""; const signature = req.header("X-Signature") ?? ""; const payload = req.body as { order_id: number; charged_amount?: number; total_price?: number; status?: string; }; const amount = payload.status === "pending" ? String(payload.total_price ?? 0) : payload.status === "failed" || payload.status === "cancelled" ? "0" : String(payload.charged_amount ?? 0); const signed = JSON.stringify({ orderId: payload.order_id, amount }); const expected = crypto.createHmac("sha256", secret).update(signed).digest("hex"); const valid = signature.length === expected.length && crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected)); if (!valid) { return res.status(401).json({ ok: false }); } return res.json({ ok: true });});