Mini apps
Payments
A mini-app payment has two steps. Your backend creates the invoice. Your page in the WebView asks the wallet to pay it.
1. Create the invoice (backend)
Call the invoices API with your mini-app API key. The mini-app context is implicit in the key.
POST /v2/api/invoices
x-api-key: YOUR_MINI_APP_API_KEY
Content-Type: application/json
{
"amount": 12.50,
"currency": "BBD",
"merchant_order_id": "order_123",
"wallet_user_id": "<sub claim from the launch token>",
"expires_at": "2026-12-31T00:00:00Z",
"metadata": { "phone_number": "246xxxxxxx" }
}
-
merchant_order_idis your idempotency key. A duplicate returns a 422 unique-constraint error. Treat that as “the invoice exists” and continue. -
wallet_user_idis the pseudonymoussubclaim from the launch token. -
metadatareturns verbatim in theinvoice.paidwebhook.
2. Request the payment (WebView)
Load the SDK and call requestPayment:
<script src="https://merchant.mmoneyapp.com/static/js/mmoney-mini-app-sdk.js"></script>
<script>
document.getElementById("pay").addEventListener("click", async () => {
try {
const result = await window.MMoneyMiniApp.requestPayment({
external_order_id: "order_123"
});
// result.status === "succeeded"
} catch (err) {
// err.status: "failed" | "cancelled" | "no_pending_invoice"
}
});
</script>
The wallet shows a native confirmation sheet and settles to your merchant account. The promise resolves with the result.
By default that confirmation is a single tap. You can require the customer to enter their PIN or password first — see Payment verification.
SDK API
// Pay the pending invoice for this user and mini app.
MMoneyMiniApp.requestPayment({ external_order_id?: string })
// Close the mini app, for example after a successful order.
MMoneyMiniApp.close()
3. Confirm on your server
mMoney sends a signed invoice.paid webhook when settlement
completes. Verify it before you fulfil. See
Verify signatures.
Errors
| Scenario | Response |
|---|---|
| Wrong API key permissions | 403. The key needs Receive Funds only. |
Duplicate merchant_order_id |
422 unique-constraint error. The invoice exists. |
Invoice past expires_at |
The pay step returns 422 “Invoice has expired”. |
| No wallet in this currency | The pay step returns 422 “No wallet address”. |
| Verification required but not supplied |
The pay step returns 401 step_up_required. The wallet prompts and retries; your page sees no change. |
| Wrong PIN or password |
401 step_up_invalid. The wallet reopens its prompt; repeated failures lock verification for a few minutes (429 step_up_locked) and the promise rejects failed. |
| Expired or wrong-audience launch token | Your JWT library raises. Ask the user to relaunch. |
| Webhook signature mismatch | Return 401. mMoney retries up to 5 times. |