Multi-Currency Support Live: USD & LRD

MTN Mobile Money Payment API Documentation

Explore our guides and RESTful APIs to collect mobile payments, disburse funds, manage subscription payments, issue embeddable payment cards, and monitor multi-currency wallet balances across Liberia—all powered by MTN Mobile Money. This API is built for serious production use only and connects directly to live services—no sandbox environment is provided.

Overview

Welcome to the official WINAGGREGATOR MOMO Payment Service API documentation. Our RESTful API enables merchants, businesses, and applications in Liberia to seamlessly process MTN Mobile Money (MoMo) collections, manage disbursements (withdrawals), verify client credentials, and monitor real-time wallet balances across supported currencies (USD and LRD).

START HERE

Start Without a Registered Business

No Business Documents to Begin

Most payment providers require a registered company before you can accept a single payment. We don't. Sign up with your phone number and your national ID or passport number, and start collecting today. You register your business once you have earned the money to pay for it.

TierWhat you provideCan collectCan withdraw
UNVERIFIED Phone number and national ID Up to $300.00 total Up to $200.00, for registration
GRACE Cap reached — documents now due Paused Registration allowance
VERIFIED Business registration approved Unlimited Unlimited
BLOCKED 14 days passed with no documents Paused Registration allowance only
Build and earn

Integrate today and collect up to $300.00. Limits are counted in USD equivalent, so LRD payments count at the platform rate.

Withdraw to register

Take out up to $200.00 — enough to cover the Liberian business registration fee — and register your business with it.

Submit and grow

Send your registration documents. Once approved, every limit is lifted and your full balance unlocks.

The 14-day clock starts when you reach $300.00, not when you sign up. If the deadline passes without documents, new collections stop. Your balance is not lost — it is held and released in full as soon as your documents are approved, and the registration allowance stays available so you can still pay the registration fee and recover your account.

Check Your Standing — GET /api/v1/compliance/status

Readable at every tier, including while blocked, so you can always see your held balance and what is needed to release it.

Submit Documents — POST /api/v1/compliance/documents

ParameterTypeDescription
company_name *stringCompany name.
secret_string *stringCompany secret key.
documents *arrayRegistry certificate numbers, TIN, or links to hosted copies.
notestringAnything the reviewer should know.
curl "https://winaggregator-mtn.com/api/v1/compliance/status?company_name=WinLib%20Enterprises&secret_string=sec_w1nL1b_98a7b6c5d4e3f2a1"
Status Response 200 OK
{
  "status": 200,
  "success": true,
  "tier": "UNVERIFIED",
  "can_collect": true,
  "collection_cap_usd": "300.00",
  "cumulative_gross_usd": "180.00",
  "remaining_cap_usd": "120.00",
  "registration_allowance_usd": "200.00",
  "registration_allowance_remaining_usd": "200.00",
  "account_balance": { "USD": "172.80", "LRD": "0.00" }
}
LICENSED

Regulatory Status & Licensing

Licensed by the LTA

WIN LIBERIA operates as a licensed Value-Added Services Aggregator in the Republic of Liberia, authorised by the Liberia Telecommunications Authority. Payments routed through this platform are handled under that licence and under our wholesale access arrangement with the mobile network operator.

Licence Record

Licence holder WIN LIBERIA
Licence type Value-Added Services Aggregator License
Reference number LTA-VASAL/WINLIBERIA-09-18-2025-005
Issuing authority Liberia Telecommunications Authority (LTA)
Date of issue September 18, 2025

Granted Under

  • The Telecommunications Act 2007 of the Republic of Liberia
  • The Amended Telecommunications Licensing Authorization Regulations (LTA-REG-0001)
  • The Regulations on the Wholesale Access to Telecommunications Networks for the Provision of Value-Added Services (LTA-REG-0011)
Verify independently

Confirm this licence directly with the Liberia Telecommunications Authority, quoting reference LTA-VASAL/WINLIBERIA-09-18-2025-005. The same record is served as JSON at GET /api/v1/legal/license.

What this licence covers. It authorises WIN LIBERIA to operate as a Value-Added Services Aggregator, providing wholesale-access value-added services over Liberian telecommunications networks. Merchants building on this platform are covered by our aggregator arrangement rather than needing their own operator agreement — which is what makes starting without a registered business possible.

Platform Advantages

Why Choose WINAGGREGATOR for MTN MoMo Integration?

Integrating MTN Mobile Money (MoMo) directly into your website, app, or enterprise platform can often involve complex telco protocols, lengthy compliance cycles, and cumbersome API environments. WINAGGREGATOR eliminates these barriers by providing a modern, developer-friendly unified API built specifically for high-reliability Mobile Money operations in Liberia.

Zero-Friction Direct Integration

Get straight to live production payment collections without complex telco sandbox setups or manual partner approvals.

Dual Currency Engine (USD & LRD)

Native support for both Liberian Dollars (LRD) and US Dollars (USD) with automated real-time exchange rate calculations.

3 Integration Methods

Choose between direct REST API calls, embeddable Hosted Payment Cards, or automated recurring subscriptions.

Bank-Grade HMAC Security

Cryptographic HMAC-SHA256 signature verification guarantees parameter integrity and prevents unauthorized payment tampering.

Real-Time WebSockets Stream

Receive instant push event notifications as soon as transactions pass on the MTN network—no polling needed.

Automated Disbursements

Easily disburse payments, process customer refunds, or pay out vendors directly to any MTN Mobile Money subscriber account.

Fast Onboarding

How It Works: The 1-Minute Integration & Payment Flow

End-to-End in ~60 Seconds

From getting your initial API keys to processing your first live customer transaction and withdrawing revenue, the WINAGGREGATOR MTN MoMo workflow takes under a minute to understand and implement.

1

Request API Secret Key (~30 Seconds)

POST /api/v1/request-secret-string

Submit your registered company_name and phone number to receive your secure API secret key. The generated secret string acts as your primary authentication credential for all transaction requests.

2

Trigger Payment or Embed Widget (~10 Seconds)

POST /api/v1/collection

Initiate a collection by sending customer phone number (msisdn), amount, and currency (USD/LRD). Alternatively, direct customers to your hosted checkout card at /pay/{company_name} for instant UI checkout.

3

Customer Phone Authorization (USSD Push) (~15 Seconds)

MTN PROMPT

The customer immediately receives an automated pop-up prompt on their MTN Mobile Money mobile phone screen asking to authorize payment. The customer inputs their secret MTN MoMo PIN code to confirm.

4

Real-Time Event Notification (Instant)

WS /ws/v1/notification

Upon PIN entry, WINAGGREGATOR broadcasts a real-time PAYMENT_COLLECTED WebSocket event with transaction reference details, net merchant amounts, and timestamps directly to your backend or app.

5

Wallet Balances & Payout Disbursements (On Demand)

POST /api/v1/withdraw

Check multi-currency balances anytime via GET /api/v1/account-balance and disburse funds to any valid MTN Mobile Money user account instantly via the withdrawal API.

Authentication

All protected API endpoints require authenticating with your registered company_name and cryptographically generated secret_string.

Security Note: Never expose your secret_string in client-side code or public repositories.

Base URL & Server Configuration

PRODUCTION ENDPOINT LIVE
https://winaggregator-mtn.com
POST

/api/v1/request-secret-string

Register a new merchant company and generate a secret string key.

Body Parameters

ParameterTypeDescription
company_name *stringMerchant business name.
company_phone_number *stringCompany phone (MSISDN e.g., 231888123456).
curl -X POST "https://winaggregator-mtn.com/api/v1/request-secret-string" \
  -H "Content-Type: application/json" \
  -d '{
    "company_name": "WinLib Enterprises",
    "company_phone_number": "231888123456"
  }'
Response Preview 200 OK
{
  "secret_string": "sec_w1nL1b_98a7b6c5d4e3f2a1",
  "message": "Your secret string has been generated successfully."
}
POST

/api/v1/regenerate-secret-string

Rotate or regenerate a new API secret string key for a registered merchant. Supports optional verification of old_secret_string.

Body Parameters

ParameterTypeDescription
company_name *stringMerchant business name.
company_phone_number *stringCompany phone (MSISDN e.g., 231888123456).
old_secret_stringstringOptional previous secret string key for authentication.
curl -X POST "https://winaggregator-mtn.com/api/v1/regenerate-secret-string" \
  -H "Content-Type: application/json" \
  -d '{
    "company_name": "WinLib Enterprises",
    "company_phone_number": "231888123456",
    "old_secret_string": "sec_w1nL1b_98a7b6c5d4e3f2a1"
  }'
Response Preview 200 OK
{
  "secret_string": "rA0edvQ6rCD2XgSJPRxACvLEf5Bn6QfF8tDZEc0l3qk",
  "message": "Your secret string key has been regenerated successfully."
}
POST

/api/v1/collection

Initiates a mobile money collection (Request-to-Pay) from a customer's phone number. Credits the net merchant amount (96% after the 4% provider fee) directly to the target currency balance (USD or LRD).

Body Parameters

ParameterTypeDescription
company_name *stringCompany name.
secret_string *stringCompany secret key.
amount *stringNumerical payment amount.
currency *stringCurrency ("USD" or "LRD").
externalID *stringMerchant reference ID.
msisdn *stringPayer phone (23188, 231888, 231555).
curl -X POST "https://winaggregator-mtn.com/api/v1/collection" \
  -H "Content-Type: application/json" \
  -d '{
    "secret_string": "sec_w1nL1b_98a7b6c5d4e3f2a1",
    "company_name": "WinLib Enterprises",
    "amount": "10.00",
    "currency": "USD",
    "externalID": "INV-2026-001",
    "msisdn": "231888123456"
  }'
Response Preview 200 OK
{
  "status": 200,
  "success": true,
  "reference_id": "98a7b6c5-d4e3-4f2a-8b1c-90123456789a",
  "transaction_status": "SUCCESSFUL",
  "gross_amount": 10.0,
  "provider_fee_deducted": 0.4,
  "net_merchant_credited": 9.6,
  "currency": "USD",
  "msisdn": "231888123456"
}

If the payer takes their time. This call waits up to 90 seconds for the PIN prompt to be confirmed. If it has not been confirmed by then you get 202 with "transaction_status": "PENDING" and a status_urlnot a failure. The payment is still live: we keep tracking it, and when the payer confirms we credit your balance and fire your webhook automatically.

Never treat PENDING as declined. Wait for the webhook, or poll the status endpoint.

{
  "status": 202,
  "success": false,
  "reference_id": "98a7b6c5-d4e3-4f2a-8b1c-90123456789a",
  "externalID": "INV-2026-001",
  "transaction_status": "PENDING",
  "status_url": "/api/v1/collection/status/98a7b6c5-d4e3-4f2a-8b1c-90123456789a"
}
GET

/api/v1/collection/status/{reference_id}

Returns the current outcome of a collection. If MTN has resolved the payment since your original request returned, this call settles it — crediting your balance and firing your webhook — before responding. It is safe to call as often as you like: a payment is only ever credited once, no matter how many times you poll.

Query Parameters

ParameterTypeDescription
company_name *stringCompany name.
secret_string *stringCompany secret key.

Transaction States

StatusMeaning
SUCCESSFULPayer confirmed. Your balance has been credited.
FAILEDDeclined, rejected or timed out. Nothing was credited.
PENDINGAwaiting the payer's PIN. Keep polling or wait for the webhook.
EXPIREDNever confirmed within 24 hours. Treated as failed.
curl "https://winaggregator-mtn.com/api/v1/collection/status/98a7b6c5-d4e3-4f2a-8b1c-90123456789a?company_name=WinLib%20Enterprises&secret_string=sec_w1nL1b_98a7b6c5d4e3f2a1"
Response Preview 200 OK
{
  "status": 200,
  "success": true,
  "reference_id": "98a7b6c5-d4e3-4f2a-8b1c-90123456789a",
  "externalID": "INV-2026-001",
  "transaction_status": "SUCCESSFUL",
  "currency": "USD",
  "gross_amount": 10.0,
  "provider_fee_deducted": 0.4,
  "net_merchant_credited": 9.6
}
HOOK

Webhooks — Payment Result Callbacks

HMAC-SHA256 Signed

Register one HTTPS URL and we will POST the final outcome of every collection to it — whether the payer confirms in two seconds or two minutes. This is the recommended way to learn a payment's fate: your server is told, so you never have to poll. Webhooks fire from every settlement path, including payments confirmed long after your original request returned.

EventFired when
payment.successfulThe payer confirmed. Your balance has already been credited when this arrives.
payment.failedThe payment was declined, rejected or timed out. Nothing was credited.
subscription.activatedA subscription's initial payment landed and the subscription is now ACTIVE.

Register Your URL — POST /api/v1/webhook/config

ParameterTypeDescription
company_name *stringCompany name.
secret_string *stringCompany secret key.
callback_urlstringPublic https:// URL. Send an empty string to disable delivery.

Delivery Headers

HeaderDescription
X-Winlib-SignatureHMAC-SHA256 hex digest of "{timestamp}.{raw body}" keyed with your secret string.
X-Winlib-TimestampISO-8601 send time. Part of the signed message — reject anything older than ~5 minutes.
X-Winlib-EventEvent name, e.g. payment.successful.
X-Winlib-DeliveryUnique delivery id. Retries of the same event reuse it — use it to deduplicate.
X-Winlib-AttemptAttempt number, 1 to 4.
curl -X POST "https://winaggregator-mtn.com/api/v1/webhook/config" \
  -H "Content-Type: application/json" \
  -d '{
    "company_name": "WinLib Enterprises",
    "secret_string": "sec_w1nL1b_98a7b6c5d4e3f2a1",
    "callback_url": "https://yourstore.com/hooks/momo"
  }'
Delivered Payload POST
{
  "event": "payment.successful",
  "delivery_id": "3f2a8b1c-90de-4a5b-8c7d-1e2f3a4b5c6d",
  "company_name": "WinLib Enterprises",
  "timestamp": "2026-08-27T14:03:11.482913+00:00",
  "reference_id": "98a7b6c5-d4e3-4f2a-8b1c-90123456789a",
  "externalID": "INV-2026-001",
  "transaction_status": "SUCCESSFUL",
  "success": true,
  "gross_amount": 10.0,
  "provider_fee_deducted": 0.4,
  "net_merchant_credited": 9.6,
  "currency": "USD",
  "msisdn": "231888123456",
  "account_balance": { "USD": "109.60", "LRD": "0.00" }
}
Retries

Up to 4 attempts with 2s, 4s and 8s backoff. Any 2xx acknowledges; everything else retries.

Idempotency

A payment settles exactly once, so an event fires once. Still key on reference_id — a retry may arrive after you already responded.

Requirements

Public https:// only. Private, loopback and internal addresses are rejected at registration.

Always verify the signature before acting on a webhook. The payload alone is not proof it came from us. Verify against the raw request body — parsing and re-serialising the JSON changes the bytes and the signature will not match. Respond 2xx as soon as you have stored the event, and do your slow work afterwards; we time out after 10 seconds.

GET

/api/v1/transactions

Every collection attempt made by your company, newest first — including payments still awaiting confirmation. Useful for reconciliation and for finding the reference_id of a payment you have lost track of.

Query Parameters

ParameterTypeDescription
company_name *stringCompany name.
secret_string *stringCompany secret key.
limitinteger1–200. Defaults to 50.
curl "https://winaggregator-mtn.com/api/v1/transactions?company_name=WinLib%20Enterprises&secret_string=sec_w1nL1b_98a7b6c5d4e3f2a1&limit=50"
Response Preview 200 OK
{
  "status": 200,
  "success": true,
  "company_name": "WinLib Enterprises",
  "transactions": [
    {
      "reference_id": "98a7b6c5-d4e3-4f2a-8b1c-90123456789a",
      "externalID": "INV-2026-001",
      "amount": "10.00",
      "currency": "USD",
      "msisdn": "231888123456",
      "status": "SUCCESSFUL",
      "net_merchant_amount": 9.6,
      "created_at": "2026-08-27T14:02:47.109882+00:00",
      "settled_at": "2026-08-27T14:03:11.402551+00:00"
    }
  ]
}
SECURITY

Idempotency & Replay Protection

24 Hour Window

Your externalID is the idempotency key. Each one may be charged once per company every 24 hours. A repeat is refused with 409 Conflict before the payer is prompted, so a retried form post, a duplicated job or a replayed checkout payload cannot charge the same customer twice.

Choose a real key

Use your own order or invoice identifier — INV-2026-001, not a timestamp. Two customers checking out in the same second would share a timestamp and the second would be refused.

Safe to retry on network errors

If we never reached MTN, the key is released and the same externalID works again. Once MTN accepts the request the key stands for the full window — even if the payment later fails.

A declined payment does not free the key

To let a customer retry after a decline, issue a new externalID (INV-2026-001-R2). This is deliberate: it makes an accidental double charge impossible.

# The same externalID sent twice within the window
curl -X POST "https://winaggregator-mtn.com/api/v1/collection" \
  -H "Content-Type: application/json" \
  -d '{
    "secret_string": "sec_w1nL1b_98a7b6c5d4e3f2a1",
    "company_name": "WinLib Enterprises",
    "amount": "10.00",
    "currency": "USD",
    "externalID": "INV-2026-001",
    "msisdn": "231888123456"
  }'
Second Attempt 409 CONFLICT
{
  "detail": {
    "message": "externalID 'INV-2026-001' was already used. Each externalID may only be charged once every 24 hours.",
    "externalID": "INV-2026-001",
    "original_reference_id": "98a7b6c5-d4e3-4f2a-8b1c-90123456789a",
    "original_requested_at": "2026-08-27T14:02:47.109882+00:00",
    "status_url": "/api/v1/collection/status/98a7b6c5-d4e3-4f2a-8b1c-90123456789a"
  }
}
SECURITY

Rate Limits

Per 60s Window

Every endpoint is rate limited. Limits apply per caller address and per tier, over a rolling 60-second window. The /mtn prefixed routes share a budget with their unprefixed equivalents.

TierLimitEndpoints
strict 10 / 60s Secret issuance and regeneration, webhook configuration.
payment 20 / 60s Collection, checkout pay, withdraw, subscription create and cancel.
read 120 / 60s Payment status, transactions, balance, subscriptions, notifications, WebSocket connects.
payer 180 / 60s Hosted checkout status polling. Counted per transaction, not per address, so payers sharing a carrier NAT are not blocked.
public 300 / 60s Documentation, hosted card pages, static assets, health.

Response Headers

HeaderDescription
X-RateLimit-LimitRequests allowed in the window for this tier.
X-RateLimit-RemainingRequests left before you are throttled.
Retry-AfterSeconds to wait. Sent on 429 responses.
Back off, do not hammer

On 429, wait for Retry-After before retrying. Prefer webhooks over polling — they cost you no requests at all.

import time
import requests

def call_with_backoff(method, url, **kwargs):
    for attempt in range(5):
        response = requests.request(method, url, **kwargs)
        if response.status_code != 429:
            return response
        # Honour the server's own wait time.
        time.sleep(int(response.headers.get("Retry-After", 5)))
    raise RuntimeError("Still rate limited after 5 attempts")
Throttled Response 429
{
  "status": 429,
  "success": false,
  "error": "Too Many Requests",
  "detail": "Rate limit of 20 requests per 60s exceeded for this endpoint. Retry in 42s."
}
CARD WIDGET

Embeddable Payment Card Component

96% Settlement (4% Fee)

Copy and paste our pre-built, ready-to-use MTN Mobile Money Payment Card directly onto your website, store, or web application. You can set the exchange rate directly in your integration code using the rate parameter (e.g., rate=200 for 1 USD = 200 LRD). Payments made through this card automatically deduct the 4% fee and credit the 96% net amount to your company account balance in real-time.

Integration Options

Option A: HTML iFrame Embed
<iframe src="https://winaggregator-mtn.com/pay/DEVOS?amount=10.00¤cy=USD&rate=200"
  width="100%" height="590px" style="border:none; border-radius:24px;" allow="payment"></iframe>
Option B: 1-Line Drop-in JS Widget
<div id="winagg-momo-card" data-company="DEVOS" data-amount="10.00" data-currency="USD" data-rate="200"></div>
<script src="https://winaggregator-mtn.com/static/js/checkout-widget.js"></script>
Option C: Direct Hosted Checkout Link
https://winaggregator-mtn.com/pay/DEVOS?amount=10.00¤cy=USD&rate=200
Security & Anti-Tamper Signature

To prevent customer tampering (e.g. changing rate=200 to rate=50 in URL), sign params on your backend with your secret_string:

# Python HMAC-SHA256 Signature
msg = "DEVOS:10.00:USD:200:INV-100"  # {company}:{amount}:{currency}:{rate}:{ref}
signature = hmac.new(secret.encode(), msg.encode(), hashlib.sha256).hexdigest()
# Add &signature={signature} to URL or data-signature="{signature}" to JS widget

Live Card Preview Open Full Page

RECURRING API

/api/v1/subscription/create

Flexible Schedule (Daily, Weekly, Monthly, Quarterly, Yearly)

Set up automated recurring subscription payments from customer MTN Mobile Money wallets. Flexible schedules supported: weekly, monthly, quarterly, yearly. Automatically executes the initial charge upon customer PIN authorization and schedules recurring charges on the next_billing_date.

When the initial payment is not confirmed in time. You get 202 and the subscription is created with status PENDING_INITIAL_PAYMENT. It does not bill in this state. When the payer confirms, it becomes ACTIVE, its billing schedule starts from that moment, and a subscription.activated webhook fires. If the payment is declined, the subscription is closed as PAYMENT_FAILED and never bills.

Poll the returned status_url or wait for the webhook. Do not retry the subscription — that would charge the customer twice.

curl -X POST "https://winaggregator-mtn.com/api/v1/subscription/create" \
  -H "Content-Type: application/json" \
  -d '{
    "company_name": "WinLib Enterprises",
    "amount": "15.00",
    "currency": "USD",
    "interval": "monthly",
    "msisdn": "231888123456",
    "externalID": "VIP-PLAN-101",
    "rate": 195.0
  }'
Response Preview 200 OK
{
  "status": 200,
  "success": true,
  "message": "Subscription successfully created and billed for interval 'monthly'.",
  "subscription": {
    "subscription_id": "SUB-8A7B6C5D4E3F",
    "company_name": "WinLib Enterprises",
    "customer_msisdn": "231888123456",
    "amount": "15.00",
    "currency": "USD",
    "interval": "monthly",
    "status": "ACTIVE",
    "next_billing_date": "2026-09-14T20:00:00.000000+00:00"
  }
}

Embeddable Subscription Card Component

Embed the Subscription Card widget on your platform using iFrame or 1-line JS script:

Option A: HTML iFrame Embed
<iframe src="https://winaggregator-mtn.com/pay/subscription/DEVOS?amount=15.00&currency=USD&interval=monthly&rate=200"
  width="100%" height="640px" style="border:none; border-radius:24px;" allow="payment"></iframe>
Option B: 1-Line Drop-in JS Widget
<div id="winagg-subscription-card" data-company="DEVOS" data-amount="15.00" data-currency="USD" data-interval="monthly" data-rate="200"></div>
<script src="https://winaggregator-mtn.com/static/js/subscription-widget.js"></script>

Live Subscription Card Preview Open Full Page

GET

/api/v1/subscriptions

Retrieve all registered subscriptions for a merchant company. Supports optional filtering by subscription status (ACTIVE, CANCELLED).

Query Parameters

ParameterTypeDescription
company_name *stringMerchant business name.
secret_string *stringCompany secret key for authentication.
statusstringOptional status filter (ACTIVE or CANCELLED).
curl -X GET "https://winaggregator-mtn.com/api/v1/subscriptions?company_name=WinLib%20Enterprises&secret_string=sec_w1nL1b_98a7b6c5d4e3f2a1&status=ACTIVE"
Response Preview 200 OK
{
  "status": 200,
  "success": true,
  "company_name": "WinLib Enterprises",
  "total_subscriptions": 1,
  "subscriptions": [
    {
      "subscription_id": "SUB-8A7B6C5D4E3F",
      "company_name": "WinLib Enterprises",
      "customer_msisdn": "231888123456",
      "amount": "15.00",
      "currency": "USD",
      "interval": "monthly",
      "status": "ACTIVE",
      "next_billing_date": "2026-09-14T20:00:00.000000+00:00"
    }
  ]
}
POST

/api/v1/subscription/cancel

Cancel or pause an active customer recurring subscription. Prevents future automatic recurring charges on the next billing date.

Body Parameters

ParameterTypeDescription
company_name *stringMerchant business name.
secret_string *stringMerchant authentication secret key.
subscription_id *stringTarget subscription ID (e.g. SUB-8A7B6C5D4E3F).
curl -X POST "https://winaggregator-mtn.com/api/v1/subscription/cancel" \
  -H "Content-Type: application/json" \
  -d '{
    "company_name": "WinLib Enterprises",
    "secret_string": "sec_w1nL1b_98a7b6c5d4e3f2a1",
    "subscription_id": "SUB-8A7B6C5D4E3F"
  }'
Response Preview 200 OK
{
  "status": 200,
  "success": true,
  "subscription_id": "SUB-8A7B6C5D4E3F",
  "message": "Subscription 'SUB-8A7B6C5D4E3F' has been cancelled successfully."
}
POST

/api/v1/withdraw

Disburse funds directly to a mobile money wallet. Verifies and deducts strictly against the requested currency balance (USD or LRD).

Body Parameters

ParameterTypeDescription
company_name *stringCompany name.
secret_string *stringSecret string key.
amount *stringWithdrawal amount.
currency *stringCurrency ("USD" or "LRD").
curl -X POST "https://winaggregator-mtn.com/api/v1/withdraw" \
  -H "Content-Type: application/json" \
  -d '{
    "company_name": "WinLib Enterprises",
    "secret_string": "sec_w1nL1b_98a7b6c5d4e3f2a1",
    "amount": "50.00",
    "currency": "USD",
    "externalID": "WD-2026-009",
    "msisdn": "231888123456"
  }'
Response Preview 200 OK
{
  "status": 200,
  "success": true,
  "reference_id": "WD-98a7b6c5-d4e3-4f2a-8b1c-90123456789a",
  "response": {
    "status": "SUCCESSFUL",
    "financialTransactionId": "654321098",
    "externalId": "WD-2026-009",
    "amount": "50.00",
    "currency": "USD"
  }
}
GET

/api/v1/account-balance

Query company wallet balances across supported currencies (USD and LRD).

Query Parameters

ParameterTypeDescription
company_name *stringCompany name.
secret_string *stringSecret key.
currencystringOptional currency filter ("USD" or "LRD"). Omit to retrieve full breakdown.
curl -X GET "https://winaggregator-mtn.com/api/v1/account-balance?company_name=WinLib%20Enterprises&secret_string=sec_w1nL1b_98a7b6c5d4e3f2a1¤cy=USD"
Response Preview 200 OK
{
  "account_balance": {
    "USD": "1450.75",
    "LRD": "5000.00"
  }
}
WS / LISTEN

/ws/v1/notification/{user_secret_string}

Open a persistent, bi-directional WebSocket connection to receive instant payment completion events (PAYMENT_COLLECTED, WITHDRAWAL_DISBURSED) in real-time with zero polling overhead. REST polling fallback is also available at GET /api/v1/notification/{user_secret_string}.

WebSocket Protocol Details

Parameter / MessageTypeDescription
user_secret_string *string (URL Path)Company authentication secret key embedded in WebSocket connection URL.
pingClient FrameSend "ping" text frame for server heartbeat verification. Server responds with {"event": "pong"}.
const secretKey = 'sec_w1nL1b_98a7b6c5d4e3f2a1';
const ws = new WebSocket(`wss://winaggregator-mtn.com/ws/v1/notification/${secretKey}`);

ws.onopen = () => console.log('Connected to WINAGGREGATOR WebSocket Stream');

ws.onmessage = (event) => {
  const payload = JSON.parse(event.data);
  console.log('Real-Time Payment Event:', payload);
};
Real-Time Event Stream Payload WEBSOCKET EVENT
{
  "event": "PAYMENT_COLLECTED",
  "externalID": "INV-2026-001",
  "reference_id": "98a7b6c5-d4e3-4f2a-8b1c-90123456789a",
  "gross_amount": 10.0,
  "net_merchant_amount": 9.8,
  "currency": "USD",
  "msisdn": "231888123456",
  "status": "SUCCESSFUL",
  "timestamp": "2026-08-14T19:45:00.000Z"
}

HTTP Error & Status Codes

StatusTypeDescription
200 OKSuccessRequest processed successfully.
202 AcceptedPendingCollection accepted asynchronously; transaction polling in progress.
400 Bad RequestErrorMissing required parameter, invalid MSISDN format, invalid currency, or insufficient account balance.
401 UnauthorizedErrorAPI user unapproved or secret string key credentials invalid.
403 ForbiddenErrorRequest amount invalid or less than $0.00.
404 Not FoundErrorClient registration credentials not found in system.