Docs
ENFR
Dashboard
API reference

Collections

A collection asks a customer to pay from their mobile money wallet. The customer approves on their phone, or enters a one-time code that you send with authorize. Follow the outcome with webhooks.

The collection object

Attributes
idstring

Unique identifier (UUID).

livemodeboolean

true for live objects, false for test objects.

objectstring

Always collection.

statusstring

Where the collection stands. succeeded, failed and expired are final.

pendingrequires_otpprocessingsucceededfailedexpired
amountinteger

Amount requested from the customer, in minor units.

currencystring

ISO 4217 currency code.

feeinteger | null

Monerail fee, set once the collection succeeds.

netinteger | null

Amount credited to your balance (amount − fee), set once the collection succeeds.

customerobject

The paying customer.

Show child attributes
namestring

Customer name.

phonestring

Mobile money number, international format without +.

countrystring

ISO 3166-1 alpha-2 country code.

operatorstring

Mobile money operator code, for example MTN or ORANGE.

descriptionstring | null

Your description.

client_referencestring | null

Your own reference, as sent at creation.

metadataobject

Key-value pairs you attached at creation.

next_actionobject | null

What the customer must do next, or null. type is customer_approval (approve on the phone; ussd_code is a fallback), otp (send the code with authorize; when ussd_code is present, the customer dials it to get the code) or redirect (send the customer to url to approve).

Show child attributes
typestring

Kind of action.

customer_approvalotpredirect
messagestring | null

Instruction from the operator, to show to your customer.

ussd_codestring | null

USSD code the customer dials: fallback for customer_approval, code generation for otp.

urlstring | null

redirect only: payment page to open for the customer.

failure_codestring | null

failed or expired, when the collection did not succeed. The payment partner gives no finer reason for collections.

failedexpired
failure_messagestring | null

Human-readable reason, when one is available.

created_atstring

Creation time, ISO 8601 (UTC).

updated_atstring

Last change, ISO 8601 (UTC).

The collection object
{
  "id": "3b8f6c1e-2a47-4d1b-9e35-7c0a9d2f4e61",
  "object": "collection",
  "livemode": false,
  "status": "pending",
  "amount": 5000,
  "currency": "XAF",
  "fee": null,
  "net": null,
  "customer": {
    "name": "Awa Ndiaye",
    "phone": "237670000999",
    "country": "CM"
  },
  "operator": "MTN",
  "description": "Order 42",
  "client_reference": "order_42",
  "metadata": {
    "order_id": "42"
  },
  "next_action": {
    "type": "customer_approval",
    "message": "A payment request was sent. The customer enters their PIN.",
    "ussd_code": "*126#"
  },
  "failure_code": null,
  "failure_message": null,
  "created_at": "2026-10-30T13:47:06.394Z",
  "updated_at": "2026-10-30T13:47:06.394Z"
}

Create a collection

POST/v1/collections

Sends a payment request to the customer’s phone. Returns 201 with the collection, or 202 if the operator has not confirmed receipt yet (the collection is then processing; its outcome arrives by webhook).

Key roles: Owner, Finance or Developer

Body
amountintegerRequired

Amount in minor units of currency (whole francs for XAF, XOF and GNF; centimes for CDF, in multiples of 100). Integer only.

currencystringRequired

ISO 4217 code. Collections in NGN are not available and return 400 currency_unsupported.

XAFXOFGNFCDFKESGHSUGXTZSRWF
phonestringRequired

Customer mobile money number. International format (237670000000 or +237 670 00 00 00), or local format if country is known.

operatorstringRequired

Operator code from List operators, for example MTN, ORANGE, WAVE, MPESA.

customerobjectRequired

The paying customer.

Show child attributes
namestringRequired

Customer name, 2 to 80 characters.

countrystringOptional

ISO 3166-1 alpha-2 code. Required to collect in a country other than the main country of the currency: XAF defaults to CM (also GA, TD, CG, CF), XOF to SN (also CI, BJ, TG, BF, ML, NE), GNF to GN, CDF to CD. See Coverage.

descriptionstringOptional

Up to 500 characters.

client_referencestringOptional

Your own reference, up to 64 characters: letters, digits and _ . : / -.

metadataobjectOptional

Up to 20 key-value pairs. Keys up to 40 characters (A-Z a-z 0-9 _ . -), values are stored as strings up to 500 characters.

Returns

Returns the new collection object with 201, or 202 when the outcome is not final yet.

Errors worth handling
HTTPCodeDescription
400currency_unsupportedThis currency is not open.
400country_unsupportedThis country is not open for this currency. See Coverage.
400operator_unsupportedUnknown operator, or refused by the payment partner for this currency.
400phone_invalidThe number cannot be read as an international number.
400test_phone_requiredTest mode: use one of the test phone numbers of this country. See Testing.
403permission_deniedThe key’s creator does not have the role required for this operation.
429rate_limitedA rate limit was reached. Wait for Retry-After seconds. See Rate limits.
503provider_unavailableThis service is not open in this mode yet.
curl https://api.monerail.com/v1/collections \
  -H "Authorization: Bearer $MONERAIL_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: a1f3c9e2-5b7d-4c21-9f80-3e6b2d1c7a45" \
  -d '{
    "amount": 5000,
    "currency": "XAF",
    "phone": "237670000999",
    "operator": "MTN",
    "customer": {
      "name": "Awa Ndiaye"
    },
    "description": "Order 42",
    "client_reference": "order_42",
    "metadata": {
      "order_id": "42"
    }
  }'
Response201
{
  "id": "3b8f6c1e-2a47-4d1b-9e35-7c0a9d2f4e61",
  "object": "collection",
  "livemode": false,
  "status": "pending",
  "amount": 5000,
  "currency": "XAF",
  "fee": null,
  "net": null,
  "customer": {
    "name": "Awa Ndiaye",
    "phone": "237670000999",
    "country": "CM"
  },
  "operator": "MTN",
  "description": "Order 42",
  "client_reference": "order_42",
  "metadata": {
    "order_id": "42"
  },
  "next_action": {
    "type": "customer_approval",
    "message": "A payment request was sent. The customer enters their PIN.",
    "ussd_code": "*126#"
  },
  "failure_code": null,
  "failure_message": null,
  "created_at": "2026-10-30T13:47:06.394Z",
  "updated_at": "2026-10-30T13:47:06.394Z"
}

Retrieve a collection

GET/v1/collections/{id}

Returns the collection. If it is still waiting, Monerail first asks the payment partner for news, so this call can also be used for polling (every few seconds at most).

Key roles: Every role

Path parameters
idstringRequired

ID of the collection.

Returns

Returns the collection object.

curl https://api.monerail.com/v1/collections/3b8f6c1e-2a47-4d1b-9e35-7c0a9d2f4e61 \
  -H "Authorization: Bearer $MONERAIL_KEY"
Response200
{
  "id": "3b8f6c1e-2a47-4d1b-9e35-7c0a9d2f4e61",
  "object": "collection",
  "livemode": false,
  "status": "succeeded",
  "amount": 5000,
  "currency": "XAF",
  "fee": 125,
  "net": 4875,
  "customer": {
    "name": "Awa Ndiaye",
    "phone": "237670000999",
    "country": "CM"
  },
  "operator": "MTN",
  "description": "Order 42",
  "client_reference": "order_42",
  "metadata": {
    "order_id": "42"
  },
  "next_action": null,
  "failure_code": null,
  "failure_message": null,
  "created_at": "2026-10-30T13:47:06.394Z",
  "updated_at": "2026-10-30T13:47:09.807Z"
}

List collections

GET/v1/collections

Newest first.

Key roles: Every role

Query parameters
limitintegerOptionalDefault 20

Number of objects to return, 1 to 100.

starting_afterstringOptional

Cursor: the ID of the last object of the previous page.

Returns

Returns a list object: data holds up to limit collection objects, and has_more tells whether more follow.

curl "https://api.monerail.com/v1/collections?limit=10" \
  -H "Authorization: Bearer $MONERAIL_KEY"
Response200
{
  "object": "list",
  "url": "/v1/collections",
  "data": [
    {
      "id": "3b8f6c1e-2a47-4d1b-9e35-7c0a9d2f4e61",
      "object": "collection",
      "livemode": false,
      "status": "succeeded",
      "amount": 5000,
      "currency": "XAF",
      "fee": 125,
      "net": 4875,
      "customer": {
        "name": "Awa Ndiaye",
        "phone": "237670000999",
        "country": "CM"
      },
      "operator": "MTN",
      "description": "Order 42",
      "client_reference": "order_42",
      "metadata": {
        "order_id": "42"
      },
      "next_action": null,
      "failure_code": null,
      "failure_message": null,
      "created_at": "2026-10-30T13:47:06.394Z",
      "updated_at": "2026-10-30T13:47:09.807Z"
    }
  ],
  "has_more": false
}

Authorize with a code

POST/v1/collections/{id}/authorize

For collections in requires_otp: sends the one-time code the customer received by SMS, or generated by dialing next_action.ussd_code. The collection moves to processing, then to its final status. In countries where the customer generates the code, 3 attempts are allowed.

Key roles: Owner, Finance or Developer

Path parameters
idstringRequired

ID of the collection.

Body
otpstringRequired

The code, 4 to 8 digits.

Returns

Returns the collection object.

Errors worth handling
HTTPCodeDescription
400otp_invalidWrong, malformed or expired code.
402otp_invalidWrong, malformed or expired code.
400otp_not_expectedThis collection is not waiting for a code (already authorized, or no code needed).
curl https://api.monerail.com/v1/collections/9e2d4a7b-61c3-4f08-8b5e-2d7f1a3c9b40/authorize \
  -H "Authorization: Bearer $MONERAIL_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "otp": "123456"
  }'
Response200
{
  "id": "9e2d4a7b-61c3-4f08-8b5e-2d7f1a3c9b40",
  "object": "collection",
  "livemode": false,
  "status": "processing",
  "amount": 2000,
  "currency": "XAF",
  "fee": null,
  "net": null,
  "customer": {
    "name": "Awa Ndiaye",
    "phone": "237690000002",
    "country": "CM"
  },
  "operator": "ORANGE",
  "description": "Order 42",
  "client_reference": "order_42",
  "metadata": {
    "order_id": "42"
  },
  "next_action": null,
  "failure_code": null,
  "failure_message": null,
  "created_at": "2026-10-30T13:47:06.394Z",
  "updated_at": "2026-10-30T13:47:09.807Z"
}

Resend the code

POST/v1/collections/{id}/resend_otp

Asks the operator to send a new code to the customer. Where the customer generates the code with a USSD code, nothing is sent: show next_action.ussd_code again.

Key roles: Owner, Finance or Developer

Path parameters
idstringRequired

ID of the collection.

Returns

Returns the collection object.

curl -X POST https://api.monerail.com/v1/collections/9e2d4a7b-61c3-4f08-8b5e-2d7f1a3c9b40/resend_otp \
  -H "Authorization: Bearer $MONERAIL_KEY"
Response200
{
  "id": "9e2d4a7b-61c3-4f08-8b5e-2d7f1a3c9b40",
  "object": "collection",
  "livemode": false,
  "status": "requires_otp",
  "amount": 2000,
  "currency": "XAF",
  "fee": null,
  "net": null,
  "customer": {
    "name": "Awa Ndiaye",
    "phone": "237690000002",
    "country": "CM"
  },
  "operator": "ORANGE",
  "description": "Order 42",
  "client_reference": "order_42",
  "metadata": {
    "order_id": "42"
  },
  "next_action": {
    "type": "otp",
    "message": "The customer received a one-time code by SMS."
  },
  "failure_code": null,
  "failure_message": null,
  "created_at": "2026-10-30T13:47:06.394Z",
  "updated_at": "2026-10-30T13:47:06.394Z"
}