Webhook events

API request

VERIFY webhook-signature

Verify X-Mainmoney-Signature on incoming webhook payloads.

# Verify HMAC-SHA256 signature (pseudo)
# signature = HMAC_SHA256(webhook_secret, raw_request_body)

Webhook events

Configure webhookUrl on your app in the Developer dashboard.

Headers

  • X-Mainmoney-Event
  • X-Mainmoney-Signature — HMAC-SHA256 of raw JSON body
  • payment_link.payment.completed
  • payment_link.payment.failed
{
  "event": "payment_link.payment.completed",
  "id": "...",
  "created": "2026-06-14T12:00:00.000Z",
  "data": {
    "reference": "order-123",
    "paymentLinkId": "...",
    "slug": "...",
    "amount": 5000,
    "currency": "CDF",
    "status": "COMPLETED",
    "environment": "SANDBOX"
  }
}

Terminal payment events

  • terminal_payment.completed
  • terminal_payment.failed
  • terminal_payment.cancelled
  • terminal_payment.expired

Full payload, headers, and signature details: Terminal payment webhooks.

{
  "event": "terminal_payment.completed",
  "id": "...",
  "created": "2026-07-27T10:12:00.000Z",
  "data": {
    "id": "clx...",
    "merchantReference": "crm-order-1001",
    "metadata": { "table": "12" },
    "terminalId": "POS-ABC123-001",
    "businessId": "...",
    "amount": 1.03,
    "currencyCode": "USD",
    "status": "COMPLETED",
    "paymentMethod": "PHONE",
    "paymentRequestId": "...",
    "environment": "SANDBOX"
  }
}

Verify signature (Node)

import crypto from "node:crypto";

function verify(rawBody, signatureHeader, webhookSecret) {
  const expected = crypto
    .createHmac("sha256", webhookSecret)
    .update(rawBody)
    .digest("hex");
  return expected === signatureHeader;
}

Delivery attempts are logged in Event Logs → Webhooks in the dashboard (filter by payment link or terminal payment source).