Custom store webhook
Send orders from any store for WhatsApp order confirmation and receive the customer's decision.
For stores without a built-in connector. Your store sends each new order to Msgera, Msgera asks the customer on WhatsApp to confirm or cancel, and (optionally) tells your store the answer.
Connect
In the dashboard, open Integrations and connect Custom store (webhook). You can give an optional callback URL (a public https:// address) to receive decisions. You get a webhook URL and a secret.
The secret is shown once
Send orders
POST each order to your webhook URL as JSON:
{
"event": "order.created",
"order": {
"id": "A-1001",
"number": "1001",
"total": "149.50",
"currency": "EGP",
"customer": { "name": "Omar", "phone": "+201000000001" },
"items": [{ "name": "Cotton T-shirt", "quantity": 2 }],
"status": "pending"
}
}| Field | Type | Description |
|---|---|---|
eventrequired | string | order.created asks the customer. order.updated tells Msgera the order moved on (shipped, delivered, completed, cancelled, refunded, failed), so it stops waiting for the customer. |
order.idrequired | string | Your order ID, up to 100 characters. |
order.totalrequired | number | string | Order total. |
order.number | string | Order number, shown to the customer only when no items are sent. |
order.items | array | Ordered items: [{ name, quantity }]. The WhatsApp message lists up to 5. |
order.currency | string | Currency code, e.g. EGP or SAR. |
order.customer.phone | string | Customer phone with country code, e.g. +201000000001. |
order.customer.name | string | Customer name. |
Sign the request
Send the header X-Msgera-Signature: sha256=<hex>, where <hex> is the HMAC-SHA256 of the exact raw request body, keyed with your secret.
const body = JSON.stringify(payload);
const signature =
"sha256=" + crypto.createHmac("sha256", secret).update(body).digest("hex");
await fetch(webhookUrl, {
method: "POST",
headers: { "Content-Type": "application/json", "X-Msgera-Signature": signature },
body,
});Msgera answers 200 (accepted, duplicate or ignored event), 400 (invalid body) or 401 (bad signature). The same body sent twice is processed once, so retrying is safe.
Customer decisions (callback)
When a callback URL is set, Msgera posts each decision to it:
{ "orderId": "A-1001", "decision": "confirm" }decision is confirm, cancel (auto-cancel on) or cancel_request (auto-cancel off: the customer asked to cancel and you decide). The request is signed the same way (X-Msgera-Signature, same secret) and carries X-Msgera-Event: order.decision. Answer with any 2xx. A 4xx marks the update as failed; a 5xx or timeout is retried a few times.
Without a callback URL, the decision is only recorded in Msgera (the Orders list on the Integrations page).