ElyonPay API Documentation
Welcome to the ElyonPay API technical documentation. This reference allows you to integrate Mobile Money payments, Visa, Mastercard and transfers into your application in just a few lines of code.
https://api.elyonpay.net/api (Sandbox) / https://api.elyonpay.org/api (Production)All requests must be sent over HTTPS. Unsecured HTTP requests are rejected. See the Environments section for details.
Key Features
- Unified Mobile Money — MTN MoMo, Orange Money, Wave, Moov, Airtel Money
- Bank Cards — Visa, Mastercard with 3D Secure, PCI DSS level 1 compliant
- Simple Integration — Payment link + iframe, active status verification
- Full Sandbox — Test for free with simulated data
- Multi-currency — XAF, XOF, EUR, USD, GBP, NGN, CDF, KES
- Official SDKs — JavaScript, PHP, Python, Java, React Native, Flutter
Quick Start
Follow these 3 steps to make your first payment:
- Contact us to get your API key
- Install the SDK for your language or use cURL directly
- Call
POST /api/request-to-pay/payment/linkwith the amount and redirect URLs
curl -X POST https://api.elyonpay.org/api/request-to-pay/payment/link \
-H "Authorization: Bearer <your_jwt_token>" \
-H "Content-Type: application/json" \
-H "language: fr" \
-d '{
"amount": 15000,
"user_lang": "fr",
"msisdn": "+237600000000",
"success": "https://yoursite.com/success",
"error": "https://yoursite.com/error"
}'Authentication
The ElyonPay API uses JWT (JSON Web Token) authentication. Obtain your token via the login endpoint, then include it in every request.
| Parameter | Type | Required | Description |
|---|---|---|---|
| username | string | Required | Merchant account email |
| password | string | Required | Account password |
| role | string | Required | ROLE_MERCHANT_ADMIN |
curl -X POST https://api.elyonpay.org/api/login \
-H "Content-Type: application/json" \
-d '{
"username": "you@example.com",
"password": "***",
"role": "ROLE_MERCHANT_ADMIN"
}'Response
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...."
}Usage in HTTP Header
Authorization: Bearer <your_jwt_token>Environments
ElyonPay offers two distinct environments to allow you to develop and test safely before going to production.
Base URLs
| Environment | Base URL | Description |
|---|---|---|
Sandbox | https://api.elyonpay.net/api | No real charges — simulated data |
Production | https://api.elyonpay.org/api | Real transactions |
Mobile Money Test Numbers
| Number | Network | Simulated Behavior |
|---|---|---|
+237600000001 | MTN MoMo | Successful payment |
+237600000002 | MTN MoMo | Insufficient balance |
+237690000001 | Orange Money | Successful payment |
+237690000002 | Orange Money | Simulated timeout |
+221700000001 | Wave | Successful payment |
Request Format
All requests and responses use JSON format. The Content-Type: application/json header is required for requests with a body.
Required Headers
| Header | Value | Required |
|---|---|---|
Authorization | Bearer {votre_token_jwt} | Required |
Content-Type | application/json | Required (POST) |
Accept | application/json | Optional |
Idempotency-Key | UUID unique | Recommended |
Standard Response Format
{
"success": true,
"data": {
"id": "pay_1A2B3C4D5E6F",
"status": "pending",
"amount": 15000,
"currency": "XAF"
},
"meta": {
"request_id": "req_xxxxxxx",
"timestamp": "2024-03-24T10:15:00Z"
}
}Create a Payment
Generates a secure payment link. The customer is redirected to this link to choose their payment method (Mobile Money, bank card) and complete the transaction.
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| amount | number | Required | Payment amount |
| user_lang | string | Required | Payment interface language (fr, en) |
| msisdn | string | Required | Phone number in international format: +237600000000 |
| success | string | Required | Redirect URL on success |
| error | string | Required | Redirect URL on error |
Response
{
"url": "https://app.elyonpay.org/t/CI032667e43abf11?success=https://www.success.com&error=https://www.error.com"
}Code Examples
cURL
curl -X POST https://api.elyonpay.org/api/request-to-pay/payment/link \
-H "Authorization: Bearer <your_jwt_token>" \
-H "Content-Type: application/json" \
-H "language: fr" \
-d '{
"amount": 15000,
"user_lang": "fr",
"msisdn": "+237600000001",
"success": "https://yoursite.com/success",
"error": "https://yoursite.com/error"
}'Node.js / JavaScript
const response = await fetch('https://api.elyonpay.org/api/request-to-pay/payment/link', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + token,
'Content-Type': 'application/json',
'language': 'fr'
},
body: JSON.stringify({
amount: 15000,
user_lang: 'fr',
msisdn: '+237600000001',
success: 'https://yoursite.com/success',
error: 'https://yoursite.com/error'
})
});
const data = await response.json();
console.log(data.url); // Payment link to redirect the customerPHP
$ch = curl_init('https://api.elyonpay.org/api/request-to-pay/payment/link');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $token,
'Content-Type: application/json',
'language: fr'
],
CURLOPT_POSTFIELDS => json_encode([
'amount' => 15000,
'user_lang' => 'fr',
'msisdn' => '+237600000001',
'success' => 'https://yoursite.com/success',
'error' => 'https://yoursite.com/error'
])
]);
$response = json_decode(curl_exec($ch), true);
echo $response['url']; // Payment linkTransactions
Retrieve the complete history of your transactions: received payments, refunds, fees.
Returns a paginated list of all your transactions. You can also retrieve details of a specific transaction via its identifier.
Transaction Detail
curl -X GET https://api.elyonpay.org/api/transactions/1553 \
-H "Authorization: Bearer <your_jwt_token>" \
-H "Accept: application/json"Response Example
{
"id": 1553,
"PSPid": "FR033169cbd9c1f1",
"uuid": "FR033169cbd9c1f1",
"creation_date": "2026-03-31T14:27:13+00:00",
"validation_date": null,
"delivery_date": null,
"amount": 100,
"totalCustomer": 100,
"state": "CREATED",
"ticket_type": "SMS_EMAIL",
"operation_code": "03",
"payer_phone_number": "+33782112127",
"beneficiary_phone_number": "+33782112127",
"payer_currency": "EUR",
"beneficiary_currency": "EUR",
"payer_country": "FR",
"beneficiary_country": "FR",
"payment": {
"name": "MOLLIE"
},
"customer": {
"phoneNumber": "+33782112127",
"email": "client@example.com"
},
"merchant": {
"id": 258,
"name": "Ma Boutique",
"city": "Paris",
"address": "10 Rue de la Paix",
"zipCode": "75002",
"type": "individual",
"country_code": "FR",
"country": "France"
},
"transactionStates": [
{
"state": "CREATED",
"date": "2026-03-31T14:27:14+00:00"
}
],
"commission_operateur": 0,
"commission_marchand": 0,
"commission_pays": 0,
"commission_customer": 0,
"deliveryPrice": 0
}Response Fields
| Field | Type | Description |
|---|---|---|
| id | integer | Internal transaction identifier |
| PSPid | string | Unique ElyonPay identifier (e.g. FR033169cbd9c1f1) |
| uuid | string | Unique identifier — same value as PSPid |
| creation_date | datetime | Creation date (ISO 8601 with timezone) |
| validation_date | datetime|null | Payment validation date — null if not yet validated |
| delivery_date | datetime|null | Delivery date — null if not applicable |
| amount | number | Transaction amount in the beneficiary's currency |
| totalCustomer | number | Total amount charged to the customer (fees included) |
| state | string | Current status: CREATED, PENDING, WAITING_FOR_PAYMENT, ACCEPTED, DELIVERED, REJECTED, DECLINED, CANCELLED |
| ticket_type | string | Notification type: SMS_EMAIL, SMS, EMAIL |
| operation_code | string | Internal operation code |
| payer_phone_number | string | Payer's phone number (international format) |
| beneficiary_phone_number | string | Beneficiary's phone number |
| payer_currency | string | Payer's currency (ISO 4217 code: EUR, XAF, XOF...) |
| beneficiary_currency | string | Beneficiary's currency |
| payer_country | string | Payer's country code (ISO 3166: FR, CM, CI...) |
| beneficiary_country | string | Beneficiary's country code |
| payment.name | string | Payment provider used (MOLLIE, MTN, ORANGE...) |
customer Object
| Field | Type | Description |
|---|---|---|
| phoneNumber | string | Customer's phone number |
| string | Customer's email address |
merchant Object
| Field | Type | Description |
|---|---|---|
| id | integer | Merchant identifier |
| name | string | Merchant or business name |
| city | string | Merchant's city |
| address | string | Postal address |
| zipCode | string | Zip code |
| type | string | Account type: individual, company |
| country_code | string | ISO 3166 country code (FR, CM, CI...) |
| country | string | Country name |
transactionStates Array
History of transaction status changes, from oldest to newest.
| Field | Type | Description |
|---|---|---|
| state | string | Status at that point (CREATED, PENDING, WAITING_FOR_PAYMENT, ACCEPTED, DELIVERED...) |
| date | datetime | Status change date |
Fees
| Field | Type | Description |
|---|---|---|
| commission_operateur | number | Telecom operator commission |
| commission_marchand | number | Merchant commission |
| commission_pays | number | Country commission |
| commission_customer | number | Commission applied to the customer |
| deliveryPrice | number | Delivery fees |
Official SDKs
Official SDKs are available for major languages and frameworks. They automatically handle authentication and errors.
Integration Flow
ElyonPay uses a 6-step model based on a payment link and active status verification (pull model). No webhook infrastructure is required.
Get a payment link
Your backend calls POST /api/request-to-pay/payment/link with the amount and redirect URLs (success / error). The API returns a unique payment URL.
Display the payment iframe
Redirect the customer to the returned URL, or embed it in an iframe. The customer chooses their payment method (Mobile Money, bank card) and enters their details.
Payment validation
The customer confirms the payment on the operator side (USSD code for Mobile Money, 3D Secure for cards). ElyonPay processes the transaction.
Redirect to your backend
Once the payment is processed, the customer is redirected to your success or error URL depending on the result. The transaction UUID is passed in the redirect URL.
Fetch the transaction status
Your backend calls GET /api/transactions/{uuid} to retrieve the definitive transaction status. This server-side check is essential — never rely solely on the redirect URL.
Display confirmation to the customer
Based on the returned status (DELIVERED, REJECTED, CANCELLED...), display the appropriate confirmation or error page to your customer.
Diagram — Payment Initiation
sequenceDiagram
participant Customer
participant Merchant
participant ElyonPay
Customer->>Merchant: Finalizes cart
Customer->>Merchant: Selects "Pay"
Merchant->>ElyonPay: POST /api/login
ElyonPay-->>Merchant: Returns JWT token
Merchant->>ElyonPay: POST /api/request-to-pay/payment/link
ElyonPay-->>Merchant: Returns payment URL
Merchant->>Customer: Displays payment page (iframe or redirect)
Customer->>ElyonPay: Selects payment method
Customer->>ElyonPay: Completes transaction
ElyonPay-->>Customer: Shows confirmation popup
Diagram — Payment Result
sequenceDiagram
participant Customer
participant Merchant
participant ElyonPay
Customer->>ElyonPay: Transaction completed
alt Successful payment
ElyonPay->>Merchant: Redirect to success URL
else Failed payment
ElyonPay->>Merchant: Redirect to error URL
end
Merchant->>ElyonPay: GET /api/transactions/[ID_TRANSACTION]
ElyonPay-->>Merchant: Returns transaction status
Merchant->>Merchant: Updates order status
Merchant->>Customer: Shows order confirmation
Implementation example (steps 1 → 5)
Node.js / Express
// 1. Create payment link
app.post('/checkout', async (req, res) => {
const response = await fetch('https://api.elyonpay.org/api/request-to-pay/payment/link', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + token,
'Content-Type': 'application/json',
'language': 'fr'
},
body: JSON.stringify({
amount: req.body.amount,
user_lang: 'fr',
msisdn: req.body.phone,
success: 'https://yoursite.com/payment/done',
error: 'https://yoursite.com/payment/error'
})
});
const { url } = await response.json();
res.redirect(url); // 2. Redirect customer to payment page
});
// 4 → 5. Handle redirect & verify status
app.get('/payment/done', async (req, res) => {
// The transaction uuid is available from your order context
const tx = await fetch(`https://api.elyonpay.org/api/transactions/${uuid}`, {
headers: { 'Authorization': 'Bearer ' + token }
}).then(r => r.json());
if (tx.state === 'DELIVERED') {
// 6. Show confirmation
res.render('success', { transaction: tx });
} else {
res.render('pending', { transaction: tx });
}
});Mobile Money
ElyonPay unifies 5 African Mobile Money networks under a single API. Each network has its own operator codes and country coverage.
Supported Networks
| Method Code | Network | Countries | Currencies |
|---|---|---|---|
mtn_mobile_money | MTN MoMo | CM, NG, CI, GH, UG | XAF, NGN, XOF |
orange_money | Orange Money | CM, CI, SN, ML | XAF, XOF |
wave | Wave | SN, CI, BF, ML | XOF |
moov_money | Moov Africa | BJ, TG, BF, NE | XOF |
airtel_money | Airtel Money | KE, TZ, UG, ZM, CD | KES, TZS, UGX, CDF |
Coverage: Cameroon, Nigeria, Ivory Coast, Ghana, Uganda, Senegal, Mali, Burkina Faso, Benin, Togo, Niger, Kenya, Tanzania, Zambia, Democratic Republic of Congo.
Bank Cards
Accept Visa and Mastercard payments with 3D Secure, tokenization and PCI DSS level 1 compliance.
Test Cards (Sandbox)
| Card Number | Expiry | CVV | Behavior |
|---|---|---|---|
4242 4242 4242 4242 | 12/28 | 123 | Successful payment |
4000 0000 0000 0002 | 12/28 | 123 | Card declined |
4000 0000 0000 3220 | 12/28 | 123 | 3D Secure required |
5555 5555 5555 4444 | 12/28 | 123 | Mastercard success |
Payment Statuses
Each payment goes through several statuses during its lifecycle.
State Transition Diagram
stateDiagram-v2
[*] --> CREATED
CREATED --> PENDING: Payment initiated
PENDING --> WAITING_FOR_PAYMENT: Awaiting customer
WAITING_FOR_PAYMENT --> ACCEPTED: Payment confirmed
PENDING --> ACCEPTED: Direct approval
PENDING --> REJECTED: Validation failed
PENDING --> DECLINED: Payment issue
WAITING_FOR_PAYMENT --> DECLINED: Payment issue
WAITING_FOR_PAYMENT --> CANCELLED: User cancellation
ACCEPTED --> DELIVERED: Funds transferred
ACCEPTED --> CANCELLED: Administrative action
REJECTED --> [*]
DECLINED --> [*]
CANCELLED --> [*]
DELIVERED --> [*]
Error Codes
In case of error, the API returns a JSON object with a machine error code and a readable message.
{
"success": false,
"error": {
"code": "INSUFFICIENT_FUNDS",
"message": "The customer's Mobile Money balance is insufficient.",
"http_status": 402
}
}Error Table
| Error Code | HTTP | Description |
|---|---|---|
| UNAUTHORIZED | 401 | Missing or invalid API key |
| INVALID_AMOUNT | 400 | Invalid amount or below minimum allowed |
| CURRENCY_NOT_SUPPORTED | 400 | Currency not supported for this network |
| PHONE_INVALID | 400 | Invalid or unregistered phone number |
| INSUFFICIENT_FUNDS | 402 | Insufficient balance on client side |
| OPERATOR_TIMEOUT | 408 | Mobile Money operator did not respond in time |
| DUPLICATE_REQUEST | 409 | Duplicate request — use Idempotency-Key |
| PAYMENT_NOT_FOUND | 404 | Payment not found |
| RATE_LIMIT_EXCEEDED | 429 | Too many requests — retry in a few seconds |
| INTERNAL_ERROR | 500 | ElyonPay internal error — contact support |
Supported Currencies
| Code | Currency | Minimum Amount | Methods |
|---|---|---|---|
XAF | Franc CFA BEAC | 100 XAF | MTN MoMo, Orange Money, Carte |
XOF | Franc CFA BCEAO | 100 XOF | Wave, Moov, Orange Money, MTN, Carte |
EUR | Euro | 0.50 EUR | Carte (Visa, Mastercard), PayPal |
USD | US Dollar | 0.50 USD | Carte, PayPal |
GBP | British Pound | 0.30 GBP | Carte |
NGN | Nigerian Naira | 100 NGN | MTN MoMo NG |
KES | Kenyan Shilling | 10 KES | Airtel Money |
CDF | Congolese Franc | 500 CDF | Airtel Money |
Sandbox & Tests
The sandbox environment lets you test the complete integration without making real payments. Connect to api.elyonpay.net — no real charges will be made.
Test Accounts by Country
Use these credentials to test the integration on the sandbox environment. Each account is associated with a specific country and currency.
| Phone | Password | |
|---|---|---|
+237683191284 | demo+23733@elyonpay.com | CompteDemo1 |
| Phone | Password | |
|---|---|---|
+2250758789285 | demo+225@elyonpay.com | CompteDemo1 |
| Phone | Password | |
|---|---|---|
+33895555555 | demo+33@elyonpay.com | CompteDemo1 |
Sandbox Limits
- Sandbox transactions incur no fees
- Data is reset every 30 days
- Limit of 1,000 requests/hour per test key
Go to Production
- Complete KYB (Know Your Business) verification in your dashboard
- Switch the base URL from
api.elyonpay.nettoapi.elyonpay.org - Verify that your redirect URLs (success / error) use HTTPS
- Configure your low balance alerts
