Docs
ENFR
Dashboard
Get started

Testing

Test mode in depth: the sandboxes, the test helpers, the dashboard simulators and a full card scenario.

Everything here uses a test key (mr_test_…) and moves no real money. Read Test mode first for how test and live data are separated.

Mobile money in test mode

Test collections and payouts never reach a real operator or a real wallet.

  • In every open country, test mode accepts only the test numbers below, and the last digit decides the outcome. Any other number returns 400 test_phone_required. Format errors (400 phone_invalid) behave as in live mode.
  • In Cameroon and Gambia, Monerails simulates the operation itself. In the other countries, it is sent to a payment partner’s test environment, always with that partner’s own test number, never with the number of a real wallet.
  • Write your code for every status: pending, requires_otp, processing, then succeeded, failed or expired. Do not assume a test collection always succeeds.
  • Collections that succeed credit your test balance. Use that balance to try payouts and settlements.

Test phone numbers

In Cameroon, Côte d’Ivoire, Senegal, Benin, Togo, Burkina Faso, Gabon, Chad, Congo, Central African Republic, Mali, Niger, Guinea-Bissau, Guinea, Gambia and DR Congo, test mode accepts only these numbers, for collections and payouts. Any other number returns 400 test_phone_required, so a test can never reach a real wallet.

Country country, currency Succeeds Stays pending Fails
Cameroon CM, XAF 237660000001 237660000002 237660000003
Côte d’Ivoire CI, XOF 2252100000001 2252100000002 2252100000003
Senegal SN, XOF 221700000001 221700000002 221700000003
Benin BJ, XOF 22900000001 22900000002 22900000003
Togo TG, XOF 22800000001 22800000002 22800000003
Burkina Faso BF, XOF 22660000001 22660000002 22660000003
Gabon GA, XAF 24100000001 24100000002 24100000003
Chad TD, XAF 23500000001 23500000002 23500000003
Congo CG, XAF 24200000001 24200000002 24200000003
Central African Republic CF, XAF 23600000001 23600000002 23600000003
Mali ML, XOF 22300000001 22300000002 22300000003
Niger NE, XOF 22700000001 22700000002 22700000003
Guinea-Bissau GW, XOF 245000000001 245000000002 245000000003
Guinea GN, GNF 224600000001 224600000002 224600000003
Gambia GM, GMD 2200000001 2200000002 2200000003
DR Congo CD, CDF 243120000011 243120000012 243120000013
  • Use any operator returned by List operators for the country. The final status arrives within a few seconds, by webhook and on the object.
  • A number ending in 2 never reaches a final status: use it to test your handling of long waits.
  • Orange Money in Guinea asks for a code: the collection is requires_otp. Send any 6-digit code with authorize. 000000, 111111, 222222, 333333 and 444444 make the collection fail; any other code lets the number decide.

Card test helpers

Two endpoints play the card issuer’s role. They need a test key and the Owner or Finance role.

Endpoint Body Effect
POST /v1/test/cardholders/{id}/verification result: approved or rejected; reason (optional, up to 200 characters) Decides a verification in in_review. With rejected, reason becomes verification.reason (default: Document unreadable (simulation)). Sends cardholder.kyc_updated.
POST /v1/test/cards/{id}/authorizations amount (US cents), merchant (optional, up to 40 characters), status: approved (default) or declined Approved: the payment and its fee are taken from the card and card.transaction is sent. Declined: nothing is charged and card.authorization_declined is sent, with reason Declined (simulation).

Test payments are simulated by Monerails: they follow the same rules as a real authorization (a frozen card, an insufficient card balance or a spending limit decline the payment, with its decline fee) but never reach the card network. When an approved request is declined by these rules, the response has status: "declined", a decline_code (card_frozen, insufficient_funds or limit_exceeded) and a message.

Test mode limits

Test card funds are shared by every business on Monerails, so card test mode has limits per business:

Limit Value
Test cards balance + money on test cards 500 USD at most
Test top-up of the cards balance 10 to 100 USD per operation
Active test cards 10 at most
Test cards issued 20 per calendar month

Above a limit, the dashboard shows a clear message and the API answers 400 test_limit_reached (429 for the monthly issuance quota). Terminate or withdraw from test cards you no longer use to free room. A test card unused for 30 days, or every test card of a business without test activity for 60 days, is emptied back to the test cards balance and terminated automatically. Need more for a demo? Contact us.

A full card scenario

  1. Top up the test cards balance. In the dashboard, in test mode, open Cards › Top up the card balance, enter an amount (10 to 100 USD in test mode) and click Credit the test balance (Owner or Finance). The test balance is credited at once; no crypto is involved in test mode.
  2. Create a cardholder.
bash
curl https://api.monerails.com/v1/cardholders \
  -H "Authorization: Bearer $MONERAIL_KEY" \
  -H "Content-Type: application/json" \
  -d '{"type": "customer", "first_name": "Awa", "last_name": "Ndiaye", "email": "awa@example.com", "phone": "+237670000999", "country": "CM", "birth_date": "1991-02-03", "id_document": "national_id",
       "documents": { "front": "data:image/jpeg;base64,/9j/4AAQ…", "back": "data:image/jpeg;base64,/9j/4AAQ…" }}'
  1. Submit the verification. The document photos are required when the cardholder is created (JPEG or PNG in base64: the API checks the format, the size, 4 MB each, and the resolution, 600 × 400 px at least) and reused here; send documents again only to replace them. verification.status becomes in_review.
bash
curl https://api.monerails.com/v1/cardholders/5df6acd9-4bac-4e19-869c-fcde6b79f389/verification \
  -H "Authorization: Bearer $MONERAIL_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "id_number": "CM12345678",
    "birth_date": "1991-02-03",
    "place_of_birth": "Douala",
    "address": { "line1": "12 rue Joss", "city": "Douala", "state": "Littoral" },
    "documents": { "front": "data:image/jpeg;base64,/9j/4AAQ…", "back": "data:image/jpeg;base64,/9j/4AAQ…" }
  }'
  1. Decide the verification. Approve it. To test your rejection path, send "result": "rejected" with a reason, read verification.reason, then submit again.
bash
curl https://api.monerails.com/v1/test/cardholders/5df6acd9-4bac-4e19-869c-fcde6b79f389/verification \
  -H "Authorization: Bearer $MONERAIL_KEY" \
  -H "Content-Type: application/json" \
  -d '{"result": "approved"}'
  1. Wait for cardholder.kyc_updated with verification.status verified, then issue a card. You get 201 with an active card, or 202 with a pending card followed by card.issued or card.issue_failed.
bash
curl https://api.monerails.com/v1/cards \
  -H "Authorization: Bearer $MONERAIL_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: test-card-awa-1" \
  -d '{"cardholder": "5df6acd9-4bac-4e19-869c-fcde6b79f389", "amount": 1000, "label": "Test card"}'
  1. Simulate payments. An approved payment, then a declined one. Check that your code handles card.transaction and card.authorization_declined, and that the declined one changed nothing on the card.
bash
curl https://api.monerails.com/v1/test/cards/ce2f0aea-7f87-4cbd-8383-03129d1253e0/authorizations \
  -H "Authorization: Bearer $MONERAIL_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amount": 400, "merchant": "Notion"}'

curl https://api.monerails.com/v1/test/cards/ce2f0aea-7f87-4cbd-8383-03129d1253e0/authorizations \
  -H "Authorization: Bearer $MONERAIL_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amount": 90000, "merchant": "Notion", "status": "declined"}'
  1. Manage the card. Fund it, withdraw from it, freeze and unfreeze it. Each action can answer 202: handle the webhook that follows.
  2. Terminate it. Terminate the card and check that card.terminated arrives and that its balance is back on the cards balance (Retrieve the balance).

Dashboard simulators

The dashboard, in test mode, has the same simulations behind buttons:

What Where Button (EN / FR)
Top up the cards balance (Owner or Finance) Cards › Top up the card balance Amount, then Credit the test balance / Créditer le solde de test
Decide a verification A cardholder in review Approve / Valider, Reject / Refuser
Pay with a card A card Simulate a payment / Simuler un achat

Test your webhooks

  • Create a test endpoint: test events only go to test endpoints, signed with their own secret.
  • To receive events on your machine, expose your local server through an HTTPS tunnel with a domain name.
  • To test your signature check without Monerails, send yourself an event signed the same way (the curl tab of Verify the signature).
  • Answer 2xx within 10 seconds, then try a failing answer and watch the retries. Use Redeliver an event to replay one.

Before going live

  • Every final status is handled: failed and expired collections, failed payouts and settlements, card.issue_failed, rejected verifications, declined card payments.
  • Every 202 is followed by a webhook, never by a second creation.
  • Your tests fail if they receive "livemode": true.

Then follow Going live.