Payment & verification

Muamla payments are wallet transfers that are verified directly with the bank. The core verb is verify, not charge.

Lifecycle

  1. Your backend creates an invoice. It returns a url and a payment reference.
  2. The customer opens the hosted page at url and picks their bank wallet.
  3. They transfer the amount from their wallet using the reference, and get a receipt reference back.
  4. They submit that receipt reference; Muamla verifies the transfer with the bank.
  5. The invoice becomes verified (or failed) and a signed webhook is sent.

Recommended: hosted checkout

The simplest integration is to redirect the customer to the invoice url (or share it as a payment link). Muamla renders the bank picker, collects the receipt reference, and runs verification for you — no payment UI to build.

typescript
// after creating the invoice on your backend
return Response.redirect(invoice.url);

Submitting a payment programmatically

The hosted page calls this public endpoint; you can also call it directly if you build your own checkout UI with a publishable key. It triggers verification for an invoice.

bash
curl -X POST https://app.muamla.org/api/checkout/inv_8x2K9aFqR3mB7nZ1/pay \
  -H "content-type: application/json" \
  -d '{ "phone": "22222222", "provider": "bankily", "reference": "9920183" }'
FieldTypeRequiredDescription
phonestringYesThe customer's wallet phone number.
providerstringNoOne of bankily, sedad, masrivi, bimbank, click, bcipay.
referencestringNoThe receipt reference the wallet returned to the customer.

Response

json
{ "status": "verified", "outcome": "verified" }

status is the new invoice status; outcome is verified or failed. Verifying an already-verified invoice is idempotent and returns verified again.

Always treat the webhook (or a server-side GET /v1/invoices/:id) as the source of truth. Never fulfil an order based on the browser alone.

Retrieve a payment

Each verification creates a payment record. Fetch one with your secret key:

bash
curl https://app.muamla.org/v1/payments/pay_8x2K9aFqR3mB7nZ1 \
  -u sk_test_your_key:
json
{
  "id": "pay_8x2K9aFqR3mB7nZ1",
  "status": "verified",
  "amount": 500000,
  "fee": 5000,
  "amount_format": "5,000 MRU",
  "fee_format": "50 MRU",
  "invoice_id": "inv_…",
  "provider": "bankily",
  "verified_at": "2026-06-29T19:01:00.000Z"
}

Sandbox verification

In test mode the customer phone decides the outcome — see Testing. Live bank verification is not enabled yet; verifying a live invoice returns a 501 not_implemented error for now.