API V2 (recommended)

Collect from a customer

POST /V2/deposits: the customer pays from their Mobile Money wallet after confirming with a PIN; your balance is credited on confirmation.

POST /V2/deposits#

Requests a payment from the customer. They get a PIN prompt on their phone; the payment stays pending until they confirm (or refuse), then moves to completed or failed.

Parameters#

FieldTypeRequiredDescription
amountstring | numberYesNet amount, > 0, at most 2 decimals (e.g. "1500", "12.50").
currencystringYesCurrency of an open country (e.g. CDF, USD), then checked against the phone number's country. Each country's currencies: Countries and providers.
phonestringYesLocal number of the default country (0812345678) or international, with the country's dial code (+243812345678). At most 20 characters. See Countries and numbers.
countrystringNoPhone number's country, 3-letter code (e.g. COD). Without it: local number = the platform's default country (currently DR Congo, COD), international number = country of the dial code.
providerstringNoProvider code (e.g. VODACOM_MPESA_COD, see Countries and providers). Inferred from the number when absent.
referencestringNoYour reference, unique per token, at most 100 characters (letters, digits, . _ : -). See idempotency.
callback_urlstringNoPublic HTTPS address that will receive the final status notification.
customer_messagestringNoText shown to the customer (SMS, history), depending on the provider: 4 to 22 characters, letters, digits and spaces.
metadataobjectNoUp to 20 key / value pairs (strings of at most 255 characters), returned as is.

Example#

Collect 1,000 CDF

curl -X POST "https://api.labyrinthe-rdc.com/api/V2/deposits" \
  -H "Authorization: Bearer test_xxxxxxxxxxxxxxxx" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"amount":"1000","currency":"CDF","phone":"0813456789","reference":"ORDER-42","callback_url":"https://boutique.example/webhooks/labpay","customer_message":"Commande 42","metadata":{"orderId":"42"}}'

With an SDK, fields follow the language conventions (callbackUrl, callback_url, CallbackUrl…) and an sdk_<uuid> reference is generated when you give none. A refusal at initiation (422 with the payment) is returned as a failed payment, not thrown.

201 response
{
  "data": {
    "id": "DEP-01JCX8Q3T6Y0V5W1Z2A3B4C5D6",
    "reference": "ORDER-42",
    "operation": "deposit",
    "livemode": false,
    "status": "pending",
    "gateway_status": "ACCEPTED",
    "amount": "1000.00",
    "fee": "35.00",
    "total_amount": "1035.00",
    "currency": "CDF",
    "country": "COD",
    "phone": "0813456789",
    "provider": "VODACOM_MPESA_COD",
    "provider_transaction_id": null,
    "failure": null,
    "metadata": {
      "orderId": "42"
    },
    "created_at": "2026-11-11T10:00:00+00:00",
    "completed_at": null,
    "refunded_amount": "0.00"
  }
}

Countries and numbers#

A single integration collects in every country open on the platform, each in its own currency. The payment's country is determined as follows:

  • country given: the number must be valid in that country, otherwise INVALID_PHONE_NUMBER; a country that is not open gives UNSUPPORTED_COUNTRY.
  • Local number without country (e.g. 0812345678): the platform's default country (default: true in GET /V2/countries).
  • International number (+… or 00…) without country: country inferred from the dial code. If the dial code belongs to a country not open yet: UNSUPPORTED_COUNTRY (the message lists the available countries).
  • The currency must be one of that country's currencies, otherwise INVALID_CURRENCY. The returned payment states its country.

International number and explicit country

curl -X POST "https://api.labyrinthe-rdc.com/api/V2/deposits" \
  -H "Authorization: Bearer test_xxxxxxxxxxxxxxxx" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"amount":"1000","currency":"CDF","phone":"+243813456789","country":"COD","reference":"ORDER-43","callback_url":"https://boutique.example/webhooks/labpay"}'

Countries open today, with their currencies and providers (read live from the platform; caps and dial codes on Countries and providers):

List temporarily unavailable

The list of countries and providers is not available at the moment. Try again in a few moments, or query GET /V2/countries and GET /V2/providers with your token.

Amounts and fees#

  • The customer pays amount + deposit fees (total_amount); your balance is credited with amount once the payment is confirmed.
  • If the provider does not accept decimals in the currency (e.g. Vodacom in CDF), the total paid by the customer is rounded up to the unit.
  • Rates and caps: see Limits and fees.

Responses#

CodeMeaning
201Accepted: awaiting the customer's confirmation.
202Unknown LabPay network response: the payment stays pending and its status is re-read automatically. This is not a failure.
200reference already used for a completed payment: the existing payment is returned.
422Invalid data (VALIDATION_ERROR, INVALID_PHONE_NUMBER…), or payment refused with data.status = failed.

Only deliver an order on completed status, received through a signed notification or read with GET /V2/payments/{id} — never on the 201 response alone.

Possible errors: KYC_REQUIRED, TOKEN_BLOCKED, INVALID_CURRENCY, UNSUPPORTED_COUNTRY, UNSUPPORTED_PROVIDER, AMOUNT_TOO_SMALL, AMOUNT_TOO_LARGE, AMOUNT_OUT_OF_BOUNDS, DAILY_LIMIT_REACHED, MAINTENANCE, DEPOSITS_DISABLED, TEST_MODE_DISABLED, PROVIDER_TEMPORARILY_UNAVAILABLE… (see Errors).