Receive real-time order status notifications from deema after checkout completion.
deema sends a webhook notification to your configured endpoint whenever an order's status changes after checkout.
Use this webhook to keep your system synchronized with real-time payment events across both
Sandbox and Production environments.
Overview
After a customer completes a checkout session (online or in-store), deema dispatches POST requests to your registered webhook URL each time the order transitions to a new status.
This enables your application to react immediately to payment confirmations, cancellations, refunds, and other lifecycle events , without polling the API.
The webhook payload structure remains consistent across both environments.
Configure your webhook URL in the deema Merchant Dashboard under Settings → Webhooks for each environment independently.
- Sandbox: Sandbox Webhook Configuration
- Production: Production Webhook Configuration
Environments
| Environment | Base Domain | Purpose |
|---|---|---|
| Sandbox | https://sandbox-api.deema.me | Test and validate your webhook integration |
| Production | https://api.deema.me | Receive live payment event notifications |
Always test your webhook handler thoroughly in Sandbox before enabling it in Production.
Sandbox payloads mirror the production format, allowing you to verify your integration without affecting real transactions.
Webhook Payload
deema sends a JSON payload via POST to your registered webhook URL.
The payload contains the core order identifiers and the current order status.
Sample Payload
{
"merchant_order_ref": "INV-40",
"order_ref": "112cee08-766e-4cce-bb45-e94fa7e294ae",
"status": "captured",
"purchase_id": 5080
}Payload Fields
| Field | Type | Description |
|---|---|---|
merchant_order_ref | string | The unique order identifier from your system, as provided during checkout creation via the merchant_order_id parameter. |
order_ref | string | The unique deema order reference (UUID) assigned to the transaction. Use this value to retrieve full order details via the Order Details API. |
status | string | The current status of the order. See Order Statuses for the complete list of possible values. |
purchase_id | integer | The deema internal purchase identifier associated with the transaction. |
The payload may vary depending on the order's lifecycle stage.
Fields such as
statusand associated amounts will reflect the most recent state of the transaction at the time of dispatch.
Order Status Reference
The status field in the webhook payload corresponds to one of the defined order statuses in the deema platform. Each status represents a specific stage in the order lifecycle , from initial creation through to capture, refund, or cancellation.
For the complete list of all possible status values and their definitions, refer to the Order Statuses page.
Handling the Webhook
Follow these steps to process incoming webhook notifications reliably:
-
Expose an HTTPS endpoint on your server that accepts
POSTrequests with aJSON body. -
Parse the JSON payload and extract the
order_ref,merchant_order_ref,status, andpurchase_idfields. -
Match the order in your system using
merchant_order_ref(your internal order ID) ororder_ref(deema's reference). -
Update your order status based on the received
statusvalue. Implement logic for each relevant status transition your business requires. -
Respond with an HTTP
200 OKto acknowledge receipt. \n\n If deema does not receive a successful response, the webhook delivery will be retried.
Example: Webhook Handler
const express = require("express");
const app = express();
app.use(express.json());
app.post("/webhooks/deema", (req, res) => {
const { merchant_order_ref, order_ref, status, purchase_id } = req.body;
console.log(`Order ${merchant_order_ref} is now: ${status}`);
// Update order status in your database
switch (status) {
case "captured":
// Payment was successfully captured — fulfill the order
break;
case "fully_refunded":
// Full refund issued — update records accordingly
break;
case "partially_refunded":
// Partial refund issued — adjust the order amount
break;
case "payment_cancelled":
// Order was cancelled — release reserved inventory
break;
default:
console.log(`Received status: ${status} for order ${order_ref}`);
}
// Acknowledge receipt to Deema
res.status(200).json({ received: true });
});
app.listen(3000, () => console.log("Webhook listener running on port 3000"));from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route("/webhooks/deema", methods=["POST"])
def deema_webhook():
payload = request.get_json()
merchant_order_ref = payload.get("merchant_order_ref")
order_ref = payload.get("order_ref")
status = payload.get("status")
purchase_id = payload.get("purchase_id")
print(f"Order {merchant_order_ref} is now: {status}")
# Update order status in your database
if status == "captured":
# Payment was successfully captured — fulfill the order
pass
elif status == "fully_refunded":
# Full refund issued — update records accordingly
pass
elif status == "partially_refunded":
# Partial refund issued — adjust the order amount
pass
elif status == "payment_cancelled":
# Order was cancelled — release reserved inventory
pass
else:
print(f"Received status: {status} for order {order_ref}")
# Acknowledge receipt to Deema
return jsonify({"received": True}), 200
if __name__ == "__main__":
app.run(port=3000)<?php
// Read the incoming webhook payload
$payload = json_decode(file_get_contents("php://input"), true);
$merchantOrderRef = $payload["merchant_order_ref"] ?? null;
$orderRef = $payload["order_ref"] ?? null;
$status = $payload["status"] ?? null;
$purchaseId = $payload["purchase_id"] ?? null;
error_log("Order {$merchantOrderRef} is now: {$status}");
// Update order status in your database
switch ($status) {
case "captured":
// Payment was successfully captured — fulfill the order
break;
case "fully_refunded":
// Full refund issued — update records accordingly
break;
case "partially_refunded":
// Partial refund issued — adjust the order amount
break;
case "payment_cancelled":
// Order was cancelled — release reserved inventory
break;
default:
error_log("Received status: {$status} for order {$orderRef}");
}
// Acknowledge receipt to Deema
http_response_code(200);
echo json_encode(["received" => true]);Best Practices
-
Always respond with HTTP
200— Return a200 OKstatus immediately upon receiving the webhook, even if your internal processing takes time. Perform heavy operations asynchronously to avoid timeouts. -
Implement idempotency — deema may send the same webhook more than once in retry scenarios. Use the
order_refto deduplicate events and prevent processing the same status change twice. -
Validate the payload — Verify that all expected fields (
merchant_order_ref,order_ref,status,purchase_id) are present before processing. -
Log all incoming payloads — Maintain a record of every webhook received for auditing, debugging, and dispute resolution purposes.
-
Use HTTPS — Ensure your webhook endpoint uses HTTPS to protect the transmitted data in transit.
-
Handle all statuses — Design your webhook handler to account for every status defined in the Order Statuses reference, including statuses you may not actively use today, to avoid unexpected failures as your integration evolves.