Mongolia Bank Transfer Gate
Accept bank-transfer pay-ins on a hosted page that shows the recipient IBAN, and send bank-account payouts in Mongolian Tugrik (MNT).
When to use it
The Mongolia Bank Transfer Gate accepts bank-transfer pay-ins on a MagicPayments-hosted page —
the payer is shown the recipient account (IBAN), the bank, and the exact amount to transfer — and sends
bank-account payouts. Amounts are in MNT (Mongolian Tugrik), which has
two decimal places: 1000000 minor units means ₮10,000.00.
| Operation | Rail | How the integration looks |
|---|---|---|
| Pay-in | Bank transfer (account number / IBAN) | Create an invoice, redirect the payer to the hosted page. |
| Pay-out | Bank account | Server-to-server call to the bank-account payout endpoint. |
This rail settles whole tugrik. The minor-unit amount must be a multiple of 100 —
1000000 (₮10,000.00) is fine, 1000050 (₮10,000.50) is rejected as an
invalid amount before anything is sent to the rail.
Signing credentials from Getting started, a pay-in
gate_id for Mongolian bank transfer, and a pay-out
cascade_id enabled for MNT bank payouts.
Pay-in — hosted bank-transfer page
-
Create the invoice
Call the gate endpoint with your
gate_idand the amount in MNT minor units. -
Redirect the payer
Send the browser to
invoice_url. Our page shows the recipient IBAN, bank, and account holder, with the exact amount to transfer. The details stay valid for a limited window (typically 15 minutes) — the page shows the payer a countdown. -
Receive the result
The payer completes the transfer in their banking app; once it is confirmed we call your
callback_urland the invoice moves topaid.
/api/invoice{
"gate_id": "mn-bank-transfer-gate",
"invoice": {
"invoice_id": "order-mn-2026-000123",
"currency": "MNT",
"amount": 1000000,
"description": "Premium plan",
"ttl_minutes": 30
},
"customer": {
"id": "cust-55021",
"full_name": "Ganbold Bat",
"phone_number": "+97688000000"
},
"workflow_hooks": {
"callback_url": "https://merchant.example.com/mp/callbacks",
"return_success_url": "https://merchant.example.com/orders/123/done",
"return_decline_url": "https://merchant.example.com/orders/123/retry"
}
}
Python
resp = signed_post("/api/invoice", {
"gate_id": "mn-bank-transfer-gate",
"invoice": {
"invoice_id": "order-mn-2026-000123",
"currency": "MNT",
"amount": 1_000_000, # ₮10,000.00 (MNT has 2 decimals)
"description": "Premium plan",
"ttl_minutes": 30,
},
"customer": {
"id": "cust-55021",
"full_name": "Ganbold Bat",
"phone_number": "+97688000000",
},
"workflow_hooks": {
"callback_url": "https://merchant.example.com/mp/callbacks",
"return_success_url": "https://merchant.example.com/orders/123/done",
"return_decline_url": "https://merchant.example.com/orders/123/retry",
},
})
redirect_url = resp.json()["invoice_url"]
Response
{
"request_status": "success",
"invoice_id": "9d1f2a7c-4b88-4c0e-9f2a-2d6e1c4b7e10",
"merchant_invoice_id": "order-mn-2026-000123",
"invoice_status": "unpaid",
"invoice_url": "https://stage.example-mp.com/public/invoice/9d1f2a7c-.../gate",
"message": "Invoice (Gate PayIn) with internal uid=9d1f2a7c-... has been created."
}
Tracking the pay-in
/api/invoice/statusresp = signed_post("/api/invoice/status", {
"merchant_invoice_id": "order-mn-2026-000123"
})
invoice = resp.json()
# invoice["status"] -> "paid" once the transfer is confirmed
# "expired" if the payer doesn't transfer before ttl_minutes elapses
The payer leaves to complete a transfer in their banking app, so the invoice can sit in
unpaid/paying for a while. Lean on the callback rather than tight polling,
and set a ttl_minutes that matches how long you'll hold the order.
The hosted page instructs the payer to transfer the exact amount shown and to pay
from an account in their own name. A rounded amount or a third-party transfer may not be
matched to the order, which surfaces as an invoice that never leaves unpaid. Make sure your
order flow doesn't promise fulfilment before the invoice is paid.
Pay-out — to a bank account
Mongolian payouts go to a bank account identified by its account number (IBAN format,
MN…). Pass the recipient's bank as a bank_title slug from the
supported-banks table below, and the account holder's name in full_name.
/api/payment/payout/bank_account{
"cascade_id": "mn-bank-payout",
"payment": {
"payment_id": "payout-mn-2026-000045",
"currency": "MNT",
"amount": 1200000,
"description": "Seller settlement"
},
"bank_account": {
"bank_title": "khan_bank",
"account_number": "MN580005005104085912",
"full_name": "Ganbold Bat"
},
"customer": {
"id": "seller-9182",
"full_name": "Ganbold Bat"
},
"workflow_hooks": {
"callback_url": "https://merchant.example.com/mp/callbacks"
}
}
Python
resp = signed_post("/api/payment/payout/bank_account", {
"cascade_id": "mn-bank-payout",
"payment": {
"payment_id": "payout-mn-2026-000045",
"currency": "MNT",
"amount": 1_200_000, # ₮12,000.00 — whole tugrik only
"description": "Seller settlement",
},
"bank_account": {
"bank_title": "khan_bank",
"account_number": "MN580005005104085912",
"full_name": "Ganbold Bat",
},
"customer": {"id": "seller-9182", "full_name": "Ganbold Bat"},
"workflow_hooks": {"callback_url": "https://merchant.example.com/mp/callbacks"},
})
payout_uid = resp.json()["payment_id"]
Supported banks
Pass one of these slugs as the recipient bank_title. The list mirrors the rail's live
bank catalogue; the destination is ultimately resolved from the IBAN, so the slug names the bank for
reconciliation and support. If a bank you need is missing, ask your account manager.
| Bank | Монгол | bank_title (send this) |
|---|---|---|
| Arig Bank | Ариг банк | arig_bank |
| Bogd Bank | Богд банк | bogd_bank |
| Capitron Bank | Капитрон банк | capitron_bank |
| Chinggis Khaan Bank | Чингис хаан банк | chinggis_khaan_bank |
| Golomt Bank | Голомт банк | golomt_bank |
| Khan Bank | Хаан банк | khan_bank |
| M Bank | М банк | m_bank |
| National Investment Bank | national_investment_bank | |
| State Bank | Төрийн банк | state_bank |
| Trade and Development Bank | Худалдаа хөгжлийн банк | trade_and_development_bank |
| TransBank | Тээвэр хөгжлийн банк | transbank |
| XacBank | Хас банк | xacbank |
Tracking the pay-out
/api/payment/statusresp = signed_post("/api/payment/status", {
"merchant_payment_id": "payout-mn-2026-000045"
})
# resp.json()["status"] -> "success" | "processing" | "decline" | "error"
Testing & go-live
- On stage, drive a pay-in to
paidand a payout tosuccessusing the test IDs. - Double-check MNT amounts: 2 decimal places, and only whole-tugrik values (minor amount ends in
00) are accepted on this rail. - Validate the payout
account_number(IBAN,MN…) before sending — a wrong account is a harddecline. - Confirm your callback handler verifies the
X-MP-Signatureand tolerates retries.