> ## Documentation Index
> Fetch the complete documentation index at: https://docs.primepay.mw/llms.txt
> Use this file to discover all available pages before exploring further.

# Accept a mobile money payment

> Charge a customer's mobile money account and confirm the result before you fulfil the order.

This recipe takes one order from "customer clicks Pay" to "order marked paid". Run it in the [sandbox](https://docs.primepay.mw/api-reference/sandbox.md) first.

**1. Show the operators at checkout**

Call `GET /mobile-money/operators?country=MW` and let the customer choose Airtel Money or TNM Mpamba. Keep the chosen operator's `refId`. The list rarely changes, so you can cache it for a day.

**2. Create the payment**

Call `POST /v1/payments/mobile-money` from your server:

```json theme={null}
{
  "amount": 25000,
  "currency": "MWK",
  "customerPhone": "+265991234567",
  "provider": "7d51b653-3c6d-46eb-b3d9-7852dfee5b26",
  "merchantOrderId": "ORDER-5531",
  "description": "2 x School shoes"
}
```

Use your order number as `merchantOrderId`, and a new `Idempotency-Key` for each payment attempt. If your request times out, send it again with the **same** key. See [Idempotency](https://docs.primepay.mw/api-reference/idempotency.md).

**3. Save the reference and tell the customer to check their phone**

Store the `reference` from the `202` response against your order. Show the customer a "Approve the payment on your phone" screen.

**4. Wait for the webhook**

PrimePay sends `payment.succeeded` or `payment.failed` to your [webhook endpoint](https://docs.primepay.mw/api-reference/webhooks.md). Check the signature, then mark the order paid only on `payment.succeeded`.

**5. Confirm before you fulfil**

Before releasing goods, call `GET /v1/payments/{reference}` and check that `status` is `success` and `amount` matches your order. This also covers a webhook that was delayed.

## If something goes wrong

| What you see | What to do |
| - | - |
| `409 duplicate_order` | A payment for this order is already in progress or paid. Use the `reference` in the response; don't start another. |
| `402` with `"status": "failed"` | The operator refused it straight away. Show the customer the reason and let them try again with a new `Idempotency-Key`. |
| A timeout or a `5xx` | Don't assume it failed. Retry with the same `Idempotency-Key`, or look the order up with `GET /v1/payments?merchantOrderId=ORDER-5531`. |

## Next steps

* [Refund a payment](https://docs.primepay.mw/recipes/refund-a-payment.md)
* [Payments overview](https://docs.primepay.mw/api-reference/payments-overview.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.