> For the complete documentation index, see [llms.txt](https://moonie.gitbook.io/mooniepay/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://moonie.gitbook.io/mooniepay/payouts/testing.md).

# Testing

MooniePay provides two ways to test payout flows in sandbox mode, each suited for different use cases. No real money is moved in the sandbox — all transactions are completely isolated from your live data.

***

### Testing Options at a Glance

| Method           | Code             | Best for                                                  |
| ---------------- | ---------------- | --------------------------------------------------------- |
| MooniePay Demo   | `mooniepay_demo` | Quick, deterministic testing with a fixed set of outcomes |
| MTN MoMo Sandbox | `momo_cm`        | Testing against the real MTN sandbox environment          |

***

### Option 1 — MooniePay Demo (`mooniepay_demo`)

MooniePay Demo is a built-in test payment method that simulates different transaction outcomes based on the **phone number** you use. It requires no external setup and works immediately in sandbox mode.

#### How it works

The outcome of a transaction is determined entirely by the phone number you pass in `phone_number`. Use one of these numbers to trigger a specific status:

| Phone Number                   | Outcome                        | Status returned |
| ------------------------------ | ------------------------------ | --------------- |
| `+237620000000` or `620000000` | ❌ Transaction fails            | `failed`        |
| `+237620000001` or `620000001` | ✅ Transaction completes        | `completed`     |
| `+237620000002` or `620000002` | ⏳ Transaction stays processing | `processing`    |

> 💡 The `+237` country code prefix is optional — `620000001` and `+237620000001` both work.

#### Example — simulating a successful payment

```json
{
  "payment_method": "mooniepay_demo",
  "amount": 5000,
  "phone_number": "+237620000001",
  "customer": {
    "first_name": "Test",
    "last_name": "User",
    "email": "test@example.com"
  },
  "description": "Test payment"
}
```

#### Example — simulating a failed payment

```json
{
  "payment_method": "mooniepay_demo",
  "amount": 5000,
  "phone_number": "+237620000000",
  "customer": {
    "first_name": "Test",
    "last_name": "User",
    "email": "test@example.com"
  },
  "description": "Test failed payment"
}
```

#### Account holder details in demo mode

Calling the [Account Holder Details](/mooniepay/payments/account-holder-details.md) endpoint with `mooniepay_demo` and any of the demo phone numbers returns a mock account:

```json
{
  "success": true,
  "data": {
    "name": "Mooniepay Demo test account",
    "phone_number": "620000001"
  }
}
```

> ⚠️ Any phone number **not** in the list above will return an `Unsupported sandbox phone number` error. Always use one of the three numbers listed.

***

### Option 2 — MTN MoMo Sandbox (`momo_cm`)

MTN Mobile Money provides a full sandbox environment that mirrors their production API. This lets you test against a real provider system, including the USSD prompt flow.

#### Setup

The MTN MoMo sandbox is available without any additional configuration on your side — it is already enabled when you use your MooniePay sandbox keys.

#### Test phone numbers

MTN provides a range of test phone numbers that simulate different outcomes. For the full list of sandbox phone numbers and their expected behaviors, refer to the official MTN MoMo Developer documentation:

👉 [MTN MoMo Developer Portal — Sandbox Testing](https://momodeveloper.mtn.com/api-documentation/testing)

#### Notes on MTN MoMo sandbox

* The sandbox does not send real USSD prompts. The MTN sandbox environment simulates status updates.
* MooniePay will poll the MTN sandbox for status updates in the same way it does in production.
* Webhooks fire normally in the sandbox — use [ngrok](https://ngrok.com/) or [Hookdeck](https://hookdeck.com/) to test them locally.

***

### Orange Money (`om_cm`) — Not Available in Sandbox

Orange Money Cameroon (`om_cm`) is a **live-only** payment method. It cannot be used in sandbox mode. Attempting to use it in sandbox will return a `422` error.

To test Orange Money flows, you must use a live API key and perform small real transactions. Alternatively, use `mooniepay_demo` to cover the same status scenarios during development.

***

### Recommended Testing Checklist

Before switching to live mode, make sure you have tested all of these:

* \[ ] Initiate a payment with `mooniepay_demo` using `620000001` → verify `completed` webhook fires
* \[ ] Initiate a payment with `mooniepay_demo` using `620000000` → verify `failed` webhook fires with `reason` and `failed_code`
* \[ ] Initiate a payment with `mooniepay_demo` using `620000002` → verify `processing` webhook fires and no completion follows
* \[ ] Call Account Holder Details with a demo phone number
* \[ ] Call Retrieve Payment and verify the full response structure
* \[ ] Call Verify Payment and confirm it returns the correct status
* \[ ] Test your webhook endpoint signature verification
* \[ ] Test your duplicate webhook handling using the `ref` field
* \[ ] Test your fallback behaviour when a webhook is not received (poll via Verify)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://moonie.gitbook.io/mooniepay/payouts/testing.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
