Moldova MIA Gate
Accept MIA instant bank pay-ins in Moldovan Leu (MDL) — the payer is redirected and approves in their banking app. Pay-in only.
When to use it
The Moldova MIA Gate accepts instant bank pay-ins over MIA, Moldova's
national instant-payments scheme. You create an invoice and redirect the payer; they land on the MIA
payment page, pick their bank and approve the transfer inside their own banking app — no card, no card
data on your side. Amounts are in MDL (Moldovan Leu, 2 decimal places — so
25000 means MDL 250.00).
| Operation | Rail | How the integration looks |
|---|---|---|
| Pay-in | MIA instant bank transfer | Create an invoice, redirect the payer; we forward them to the MIA payment page. |
| Pay-out | — | Not supported on this method (see below). |
The Moldova MIA Gate is a collection-only method — there is no MIA payout rail behind it. Don't build a disbursement flow against this gate. If you need to send funds out, ask your account manager which payout-capable cascade to use and follow the matching guide.
You need your signing credentials from Getting started and a
pay-in gate_id for the Moldova MIA gate. Your account manager provides it.
How the redirect flow works
Unlike the gates where we render the payment form ourselves, this one hands the payer straight to the MIA payment page. You never see or collect bank credentials.
-
Create the invoice
Call the gate endpoint with your
gate_id, the amount in MDL minor units, and — required on this gate — acustomer.id. -
Redirect the payer
Send the customer's browser to the
invoice_urlwe return. We create the payment and forward them to the MIA payment page; there is no intermediate form of ours to fill in. - Payer approves in their banking app They choose their bank and confirm the transfer. MIA settles instantly.
-
Receive the result
We call your
callback_urlon every status change. Poll invoice status as a fallback — but see Tracking the pay-in below, because the callback is what actually settles this rail.
Pay-in — MIA instant transfer
/api/invoice{
"gate_id": "md-mia-gate",
"invoice": {
"invoice_id": "order-md-2026-000123",
"currency": "MDL",
"amount": 25000,
"description": "Wallet top-up",
"ttl_minutes": 20
},
"customer": {
"id": "cust-88412",
"full_name": "Ion Popescu"
},
"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": "md-mia-gate",
"invoice": {
"invoice_id": "order-md-2026-000123",
"currency": "MDL",
"amount": 25_000, # MDL 250.00 (2 decimals)
"description": "Wallet top-up", # shown to the payer in their banking app
"ttl_minutes": 20,
},
"customer": {
"id": "cust-88412", # required on this gate - see below
"full_name": "Ion Popescu",
},
"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"] # send the payer here
Response
{
"request_status": "success",
"invoice_id": "7e2c9a14-3d55-4f80-b1a2-6c0d9e3f8a44",
"merchant_invoice_id": "order-md-2026-000123",
"invoice_status": "unpaid",
"invoice_url": "https://stage.example-mp.com/public/invoice/7e2c9a14-3d55-4f80-b1a2-6c0d9e3f8a44",
"message": "Invoice (Gate PayIn) with internal uid=7e2c9a14-... has been created."
}
customer is optional on the invoice API in general, but this rail needs a stable customer
identifier and the payment fails at creation without one. Send your own customer id in
customer.id — the same value for the same person across invoices. If you already send it
under client_id or customer_id we'll read those too, but customer.id
is the field to use.
Your invoice.description becomes the payment reference shown in the payer's banking app,
so keep it short and recognisable — the payer reads it while deciding whether to approve. The field holds
35 bytes, and anything longer is cut: that is 35 plain characters, but Romanian
diacritics (ă, î, ș, ț) take two bytes each, so "Achitare serviciu ăîșț 12345" is 28 characters
but 32 bytes.
Omit the field and we fall back to our own payment identifier. Reconcile on
merchant_invoice_id from the callback either way.
To have us redirect straight to the payment page from the create call, set
"redirect_to_gate_payment_page": true at the top level of the request body and follow the
303 redirect instead of reading invoice_url.
Tracking the pay-in
Look the invoice up by your own id (or our invoice_uid). It reaches paid once MIA
confirms the transfer.
/api/invoice/statusresp = signed_post("/api/invoice/status", {
"merchant_invoice_id": "order-md-2026-000123"
})
invoice = resp.json()
# invoice["status"] -> "paid" | "payment_failed" | "expired" | "declined_by_payer" | ...
# invoice["actual_payment"]["processing_info"]["amount_acquired"] -> settled MDL minor units
On this rail the payer's confirmation is what moves the invoice to paid; an unconfirmed
payment stays in paying until ttl_minutes runs out and then lands in a failure
state. Polling faster does not make an abandoned payment resolve sooner. The payment link expires on the
same clock — send the payer there promptly, because a link opened after the invoice has expired is dead.
Set ttl_minutes to how long you are willing to hold the order, and handle the callback.
Pay-out
The Moldova MIA Gate does not support payouts. There is no payout endpoint to call for this method. For disbursements, use a payout-capable cascade and the relevant guide, or contact your account manager.
Testing & go-live
- On stage, use the test
gate_idfrom your account manager; no real funds move. - Drive a pay-in all the way to
paid, and confirm your handling of an abandoned payment that expires atttl_minutes. - Confirm your MDL amount conversion:
amountis minor units with 2 decimal places. - Check that every invoice you create carries a
customer.id— a missing one fails the payment, not the create call, so it shows up as a failed invoice rather than a400. - Make sure your callback handler verifies the
X-MP-Signatureand is idempotent. - Swap base URL and credentials to production; the request shape is identical.