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)Configure webhookUrl on your developer app. MainMoney POSTs JSON when a terminal payment reaches a terminal state.
| Event | When |
|---|---|
terminal_payment.completed | Cashier completed payment on the terminal |
terminal_payment.failed | Payment failed on the terminal |
terminal_payment.cancelled | You cancelled a PENDING request |
terminal_payment.expired | TTL elapsed without completion |
| Header | Description |
|---|---|
X-Mainmoney-Event | Event name (same as event in body) |
X-Mainmoney-Signature | Hex HMAC-SHA256 of the raw JSON body using your app whsec_… secret |
Content-Type | application/json |
HMAC-SHA256(signingSecret, rawBody) → hex digest.X-Mainmoney-Signature with a constant-time equals.Reject the request if the signature does not match.
{
"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",
"expiresAt": "2026-07-27T10:16:00.000Z",
"completedAt": "2026-07-27T10:12:01.000Z",
"cancelledAt": null,
"createdAt": "2026-07-27T10:11:00.000Z"
}
}
paymentMethod is set when the cashier finishes: PALM | PHONE | QR | CASH.
Use the terminal-payments-demo with ngrok so MainMoney can reach POST /webhooks. See that repo’s README.