Build with Mobile Money.
Ship faster.
Complete integration guides for the Xyle Payments WordPress Plugin and REST API. Start by creating your account, then follow the guide for your integration type.
Before You Begin
Whether you're using the WordPress Plugin or the REST API, every Xyle Payments integration begins with the same two steps: creating your account and generating your API keys from your dashboard.
Create a Xyle Payments Account
You must have an active Xyle Payments account before using any of our services. Registration takes under two minutes.
Dashboard & Generating API Keys
Your dashboard is where you manage API keys, view transactions, purchase plugin licenses, and monitor your integration status.
xk_pub_…) and a secret key (xk_sec_…).| Key type | Prefix | Use for |
|---|---|---|
xk_pub_… | Public | Client-side identification (safe to expose) |
xk_sec_… | Secret | Server-side API calls — keep private |
xk_sb_pub_… | Sandbox public | Testing — no real money |
xk_sb_sec_… | Sandbox secret | Sandbox server-side calls |
WordPress Plugin
The Xyle Payments WordPress plugin lets you accept MTN MoMo and Airtel Money on any WordPress or WooCommerce site with zero backend code. You need both an active Xyle Payments account and a plugin license before you can activate the plugin.
Purchase a Plugin License
The plugin requires a paid license key tied to your Xyle Payments account. Without it, the plugin will not activate.
XP-XXXX-XXXX-XXXX-XXXX. You will need this during plugin setup.- ✓MTN MoMo
- ✓Airtel Money
- ✓Shortcode widget
- ✓Email support
- ✓Everything in Starter
- ✓WooCommerce integration
- ✓Cashout support
- ✓Transaction analytics
- ✓Priority support
Installing the Plugin
Install directly from your WordPress admin — no FTP or command line required.
xyle-payments.zip.xyle-payments.zip, then click Install Now.wp_xylep_transactions table automatically.xyle-payments folder to /wp-content/plugins/ via FTP, then activate from the Plugins list in wp-admin.Configuring the Plugin
Enter your license key and Xyle API key in the plugin settings, then select your environment.
https://api.xyle-payments.comSandbox: https://sandbox.xyle-payments.comXP-XXXX-XXXX-XXXX-XXXX) and click Activate License.xk_sb_sec_…) for development, live key (xk_sec_…) for production.sandbox.xyle-payments.com; no real money moves. Switch to Live only when ready.wp-config.php — both sit outside your web root and are excluded from most git setups.Shortcode Usage
Place the payment widget anywhere on your site using the shortcode.
[xylep_payment_form amount="5000" theme="dark" title="Pay Now"]
In a PHP template
// Static amount echo do_shortcode( '[xylep_payment_form amount="5000"]' ); // Dynamic amount from post meta $amount = get_post_meta( get_the_ID(), '_product_price', true ); echo do_shortcode( "[xylep_payment_form amount="{$amount}" theme="dark"]" );
Set amount via JavaScript
document.getElementById('xylep-amount').value = '25000';
Shortcode Attribute Reference
Shortcode: [xylep_payment_form]
| Attribute | Default | Values | Description |
|---|---|---|---|
amount | empty | Any positive number | Pre-fills the amount field. Leave empty to set via JavaScript. |
theme | Plugin setting | light / dark | Widget colour theme. Users can toggle in-widget. |
title | Mobile Money Payment | Any string | Heading shown at the top of the form. |
currency | UGX | ISO 4217 code | Currency shown to the user. Must match the provider's accepted currency. |
WooCommerce Integration Example
Accept mobile money at WooCommerce checkout with a complete polling flow.
Step 1 — Render the widget
$order = wc_get_order( $order_id ); $amount = (int) $order->get_total(); echo do_shortcode( "[xylep_payment_form amount="{$amount}"]" );
Step 2 — Poll and complete the order
async function pollPaymentStatus(ref, orderId) { const iv = setInterval(async () => { const data = await (await fetch(`/wp-json/xylep/v1/status/${ref}`)).json(); if (data.status === 'successful') { clearInterval(iv); await fetch('/wp-json/xylep/v1/order-paid', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ order_id: orderId, xyle_ref: ref }) }); window.location.href = `/checkout/order-received/${orderId}/`; } }, 3000); }
Cashout / Withdrawal Integration
Let users withdraw funds to mobile money — always validate eligibility server-side before rendering the widget.
if ( isset( $_POST['withdraw_amount'] ) ) { $amount = absint( $_POST['withdraw_amount'] ); $balance = (int) get_user_meta( get_current_user_id(), 'wallet_balance', true ); if ( $amount > 500 && $amount <= $balance ) { echo do_shortcode( "[xylep_payment_form amount="{$amount}" title="Confirm Withdrawal"]" ); } else { echo '<p class="error">Invalid amount or insufficient balance.</p>'; } }
Transaction Tracking
Query the Xyle database table directly from PHP to check or display transaction history.
global $wpdb; $table = $wpdb->prefix . 'xylep_transactions'; $tx = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$table} WHERE transaction_ref = %s", $ref ) ); if ( $tx->status === 'successful' ) { // Fulfil the order } // Columns: id · transaction_ref · provider · phone · amount // currency · status (pending|successful|failed) // provider_ref · note · created_at · updated_at
Troubleshooting
Plugin menu not appearing after activation
Go to Settings → Permalinks and click Save Changes to flush rewrite rules — this registers the plugin's REST routes.
License activation fails
Make sure your account is active and the key is copied exactly. If the error persists, check that your server can reach api.xyle-payments.com — some hosts block outbound HTTP from PHP.
Payments fail with provider error after setup
Check that your Xyle API secret key is correct and matches the selected environment (sandbox vs live). Verify in Xyle Payments → Dashboard that your account status shows as active.
Payment request returns 502
Common causes: wrong environment, expired token, or invalid phone format. Check your PHP error log for the full API response body.
Status always shows PENDING
In sandbox you must manually approve payments from the Xyle sandbox portal. In production the subscriber receives a USSD prompt — they must enter their PIN within 60–120 s.
Widget CSS not loading
The plugin only enqueues assets on pages containing the [xylep_payment_form] shortcode. Ensure it is in the page body and the template calls wp_head().
REST API
The Xyle Payments REST API lets you initiate and track mobile money payments from any language or platform. The request body is identical across all endpoints — only the base URL changes depending on your environment.
Overview & Base URLs
All requests are made over HTTPS. Only the base URL changes between sandbox and live — the paths and request bodies are identical.
Authentication
Pass your Xyle Payments secret key as a Bearer token in the Authorization header on every request.
Authorization: Bearer xk_sec_your_secret_key_here
Content-Type: application/jsoncURL example
curl -X POST https://api.xyle-payments.com/api/v1/client/deposit \ -H "Authorization: Bearer xk_sec_your_key" \ -H "Content-Type: application/json" \ -d '{"account":"256771234567","amount":25000,"provider":"MTN_UGANDA"}'
JavaScript example
const res = await fetch('https://api.xyle-payments.com/api/v1/client/deposit', { method: 'POST', headers: { 'Authorization': 'Bearer xk_sec_your_key', 'Content-Type': 'application/json', }, body: JSON.stringify({ account: '256771234567', amount: 25000, provider: 'MTN_UGANDA' }), });
Initiate a Payment
Send a payment request to a subscriber's mobile money wallet. They receive a USSD prompt to confirm.
POST https://sandbox.xyle-payments.com/sandbox/api/v1/client/deposit
POST https://api.xyle-payments.com/api/v1/client/deposit
Request body
{
"account": "256771234567", // Required — international format, no +
"amount": 25000, // Required — smallest currency unit (UGX)
"provider": "MTN_UGANDA", // Required — "MTN_UGANDA" or "AIRTEL_UGANDA"
}Success response
{
"success": true,
"message": "Deposit processed successfully",
"data": {
"id": "transaction-uuid-456",
"type": "DEPOSIT",
"amount": 50000,
"provider": "MTN_UGANDA",
"reference": "XYLE-DEP-20260219-001",
"status": "COMPLETED",
"account": "256700000000",
"netAmount": 50000,
"createdAt": "2026-02-19T11:00:00Z",
"completedAt": "2026-02-19T11:00:30Z"
}
}| Field | Required | Description |
|---|---|---|
account | Required | International format without + (e.g. 256771234567) |
amount | Required | Amount in smallest currency unit (UGX has no decimals) |
provider | Required | MTN_UGANDA or AIRTEL_UGANDA |
Withdraw Funds
Send funds from your wallet to a subscriber's mobile money account. The transfer is processed immediately.
POST https://sandbox.xyle-payments.com/sandbox/api/v1/client/withdrawal
POST https://api.xyle-payments.com/api/v1/client/withdrawal
Request body
{
"account": "256700000000", // Required — international format, no +
"amount": 25000, // Required — smallest currency unit (UGX)
"provider": "AIRTEL_UGANDA", // Required — "MTN_UGANDA" or "AIRTEL_UGANDA"
}Success response
{
"success": true,
"message": "Withdrawal processed successfully",
"data": {
"transactionId": "transaction-uuid-789",
"reference": "XYLE-WD-20260219-001",
"amount": 25000,
"platformFee": 500,
"netAmount": 24500,
"status": "PENDING"
}
}Error response
{
"success": false,
"message": "Insufficient balance. Required: 25500, Available: 15000"
}| Field | Required | Description |
|---|---|---|
account | Required | International format without + (e.g. 256700000000) |
amount | Required | Amount in smallest currency unit (UGX has no decimals) |
provider | Required | MTN_UGANDA or AIRTEL_UGANDA |
Get Transactions
Retrieve a paginated list of all transactions associated with your account.
GET https://sandbox.xyle-payments.com/sandbox/api/v1/client/transactions
GET https://api.xyle-payments.com/api/v1/client/transactions
Query parameters
| Parameter | Required | Description |
|---|---|---|
page | Optional | Page number — defaults to 1 |
limit | Optional | Items per page — defaults to 10 |
Success response
{
"success": true,
"data": {
"transactions": [
{
"id": "transaction-uuid-456",
"type": "DEPOSIT",
"amount": 50000,
"provider": "MTN_UGANDA",
"reference": "XYLE-DEP-20260219-001",
"status": "COMPLETED",
"platformFee": 0,
"netAmount": 50000,
"createdAt": "2026-02-19T11:00:00Z"
},
{
"id": "transaction-uuid-789",
"type": "WITHDRAWAL",
"amount": 25000,
"provider": "AIRTEL_UGANDA",
"reference": "XYLE-WD-20260219-001",
"status": "PENDING",
"platformFee": 500,
"netAmount": 24500,
"createdAt": "2026-02-19T10:45:00Z"
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 25,
"pages": 3
}
}
}Check Payment Status
Poll this endpoint after initiating a payment. Recommended interval: every 3–5 seconds for up to 2 minutes.
GET https://sandbox.xyle-payments.com/v1/payments/{ref}GET https://api.xyle-payments.com/v1/payments/{ref}Response
{
"transaction_ref": "xp_2025_abc123def456",
"status": "successful", // pending | successful | failed
"provider_ref": "MTN_REF_XYZ789",
"phone": "256771234567",
"amount": 25000,
"currency": "UGX",
"provider": "mtn",
"reference": "order-1234",
"created_at": "2025-02-15T10:32:00Z"
}Error Reference
All errors return JSON with a machine-readable code and a human-readable message.
{
"success": false,
"code": "invalid_phone",
"message": "The phone number is not a valid Ugandan mobile number."
}| HTTP | Code | Description |
|---|---|---|
| 401 | unauthorized | Missing or invalid Authorization header or secret key |
| 402 | insufficient_funds | Subscriber's mobile money balance is too low |
| 422 | invalid_phone | Phone number format is not valid |
| 422 | invalid_amount | Amount is zero, negative, or exceeds provider limits |
| 422 | invalid_provider | Provider must be mtn or airtel |
| 429 | rate_limited | Too many requests — retry after the Retry-After header value |
| 502 | provider_error | Provider API error — check environment and credentials |
| 503 | service_unavailable | Xyle Payments temporarily unavailable — retry with exponential backoff |