MONA Pay IP addresses

MONA Pay webhooks originate from IP 103.168.55.14 (the api.monapay.vn server, alias ipn.mona.host), checked on 28/08/2026. If your firewall only allows certain IPs to reach the webhook endpoint, add this address to the allow list. If it ever changes we update this page first and notify the account email in advance; re-read this page or its dia-chi-ip.md version whenever webhook logs show the CONNECTION label.

IP list

Purpose IP Notes
Sending webhooks to your server 103.168.55.14 IPv4, both real webhooks and test deliveries
API api.monapay.vn (you call in) 103.168.55.14 No outbound whitelist needed unless your server blocks outbound traffic

Whitelisting still needs signature verification

Filtering by IP reduces noise but does not replace authentication: anyone behind a proxy or spoofing X-Forwarded-For can slip through if your server trusts that header. Always enable HMAC_SHA256 and check X-Mona-Signature + X-Mona-Timestamp as described in Webhook security. The IP whitelist is a second layer, never the only one.

Sample configurations

nginx: only let the MONA Pay IP reach the webhook path

location = /webhook/monapay {
    allow 103.168.55.14;
    deny all;
    proxy_pass http://127.0.0.1:3000;
}

ufw (open the port to MONA Pay only; port 443 usually also serves your website, so this is rarely used — prefer the nginx rule above):

sudo ufw allow from 103.168.55.14 to any port 443 proto tcp

Cloudflare WAF: if your site sits behind Cloudflare, create a rule “URI Path equals /webhook/monapay AND IP Source Address is not in {103.168.55.14} → Block”. Disable challenges (JS challenge, Bot Fight Mode) for the webhook path: MONA Pay is a machine caller and cannot pass a browser challenge; the log will show HTTP_4XX or HTTP_5XX if you forget.

PHP: check the IP at the application layer (when you cannot edit nginx)

<?php
$allowed = ['103.168.55.14'];
$ip = $_SERVER['REMOTE_ADDR'] ?? '';
// Behind a trusted proxy (Cloudflare), read CF-Connecting-IP instead of X-Forwarded-For
if (!in_array($ip, $allowed, true)) {
    http_response_code(403);
    exit('IP not allowed');
}

Node (Express)

const ALLOWED = new Set(['103.168.55.14']);
app.post('/webhook/monapay', (req, res, next) => {
  const ip = req.ip.replace('::ffff:', ''); // app.set('trust proxy', ...) when behind Cloudflare/nginx
  if (!ALLOWED.has(ip)) return res.status(403).send('IP not allowed');
  next();
});

Quick check

See where the MONA Pay hostnames currently resolve:

dig +short api.monapay.vn
dig +short ipn.mona.host

Both returning 103.168.55.14 means you are on the current version. Send a test with POST /api/v1/client-webhooks/test, then read request_headers and status_code in GET /api/v1/webhook-logs to confirm the firewall is open.

Common problems

Log label IP-related cause Fix
CONNECTION Your firewall blocks connections from 103.168.55.14 Add the IP to the allow list, check ufw status and security groups
HTTP_4XX (403) An allow/deny rule or WAF blocks it Review the rule, disable challenges for the webhook path
TIMEOUT The firewall drops packets instead of rejecting Change the rule to allow; MONA Pay waits at most 10 seconds