v1Beta

KiNG FLEXY GH
Developer API

Purchase data bundles programmatically. Integrate directly into your apps using your wallet balance and agent pricing.

Base URLhttps://kingflexygh.com/api/v1
Authentication Header
Authorization: kf_live_your_api_key_here
Section:Authentication

1Authentication

All API requests must include your API key in the Authorization header — no Bearer prefix required.

Authorization: kf_live_your_api_key_here
⚠️

Important: Your API key is shown only once when generated. Store it securely — losing it requires generating a new key, which permanently revokes the old one.

Getting Your API Key

  1. 1Log in to your KingFlexyGh account (agent role required)
  2. 2Navigate to Dashboard → Developer API
  3. 3Click Generate API Key and accept the policy
  4. 4Copy and store the key — it will not be shown again
  5. 5Wait for admin approval (status: pending → active)

2Response Format

All responses follow a consistent JSON structure:

Success

{
  "success": true,
  "data": { ... },
  "meta": {
    "timestamp": "2026-...",
    "version": "v1"
  }
}

Error

{
  "success": false,
  "error": {
    "code": 400,
    "message": "..."
  }
}

3Endpoints

Five endpoints — all require a valid API key in the Authorization header.

GET/api/v1/packages

List all available data packages with pricing for your account role. Call this first to discover valid network and size combinations.

Query Parameters

networkstringoptionalFilter by network: MTN, Telecel, AT-iShare, AT-BigTime (case-sensitive)
size_gbnumberoptionalFilter by exact GB size e.g. 5

Response

{
  "success": true,
  "data": {
    "packages": [
      {
        "id": "uuid-...",
        "network": "MTN",
        "size": "5GB",
        "volume_gb": 5,
        "price": 4.50,
        "currency": "GHS"
      }
    ],
    "total": 12
  }
}
  • Price is your role-specific price (agent, dealer, or standard customer).
  • Only packages with is_available = true are returned.
  • Use this to validate network/size combinations before placing orders.

Code Sample

cURL
# All packages
curl -X GET https://kingflexygh.com/api/v1/packages \
  -H "Authorization: kf_live_your_api_key_here"

# Filter by network
curl -X GET "https://kingflexygh.com/api/v1/packages?network=MTN" \
  -H "Authorization: kf_live_your_api_key_here"

# Filter by network + size
curl -X GET "https://kingflexygh.com/api/v1/packages?network=MTN&size_gb=5" \
  -H "Authorization: kf_live_your_api_key_here"
POST/api/v1/data/purchase

Purchase a single data bundle for a recipient phone number. Deducts from your wallet instantly.

Request Body

{
  "network": "MTN",
  "volume_gb": 5,
  "recipient": "0551617309",
  "reference": "order_001"
}

Response

{
  "success": true,
  "data": {
    "order_id": "uuid-...",
    "reference": "order_001",
    "status": "pending",
    "network": "MTN",
    "size": "5GB",
    "recipient": "0551617309",
    "price": 4.50,
    "new_balance": 120.50
  }
}
  • reference is your idempotency key — sending the same reference twice returns the existing order without double-charging.
  • status is usually "pending", but MAY be "queued" if the recipient number still needs registration on our network — it auto-releases to pending and is fulfilled shortly after. Poll GET /api/v1/orders/{reference} to track it.
  • network must be one of: MTN, Telecel, AT-iShare, AT-BigTime (case-sensitive).
  • volume_gb must match an available package. Use GET /packages to confirm.
  • recipient must be a valid Ghana number: 0XXXXXXXXX (10 digits, starts with 0).

Code Sample

cURL
curl -X POST https://kingflexygh.com/api/v1/data/purchase \
  -H "Authorization: kf_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "network": "MTN",
    "volume_gb": 5,
    "recipient": "0551617309",
    "reference": "order_001"
  }'
POST/api/v1/data/bulk

Purchase up to 100 data bundles in a single atomic batch. Total cost is deducted at once — either all succeed or none.

Request Body

{
  "orders": [
    {
      "network": "MTN",
      "volume_gb": 5,
      "recipient": "0551617309",
      "reference": "b_001"
    },
    {
      "network": "Telecel",
      "volume_gb": 2,
      "recipient": "0201234567",
      "reference": "b_002"
    }
  ]
}

Response

{
  "success": true,
  "data": {
    "orders_placed": 2,
    "total_cost": 7.00,
    "new_balance": 113.50,
    "orders": [
      { "order_id": "...", "reference": "b_001", "status": "pending" }
    ]
  }
}
  • Maximum 100 orders per batch request.
  • Atomic: if any order fails validation, none are charged.
  • Each order in the array follows the same rules as single purchase.

Code Sample

cURL
curl -X POST https://kingflexygh.com/api/v1/data/bulk \
  -H "Authorization: kf_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "orders": [
      {"network":"MTN","volume_gb":5,"recipient":"0551617309","reference":"b_001"},
      {"network":"Telecel","volume_gb":2,"recipient":"0201234567","reference":"b_002"}
    ]
  }'
GET/api/v1/wallet/balance

Retrieve your current wallet balance in GHS. Use before large orders to verify you have sufficient funds.

Response

{
  "success": true,
  "data": {
    "balance": 124.50,
    "currency": "GHS"
  }
}
  • Top up your wallet via the web dashboard at kingflexygh.com/dashboard/wallet.
  • Check balance before bulk orders to prevent partial failures due to insufficient funds.

Code Sample

cURL
curl -X GET https://kingflexygh.com/api/v1/wallet/balance \
  -H "Authorization: kf_live_your_api_key_here"
GET/api/v1/orders/{reference}

Check the fulfillment status of an order using the reference code you provided when placing it.

Response

{
  "success": true,
  "data": {
    "order_id": "uuid-...",
    "reference": "order_001",
    "status": "completed",
    "network": "MTN",
    "size": "5GB",
    "recipient": "0551617309",
    "price": 4.50,
    "source": "api",
    "created_at": "2026-..."
  }
}
  • Use the same reference you passed when calling /data/purchase or /data/bulk.
  • Status lifecycle: pending | queued → processing → completed | failed | refunded.
  • pending — order accepted and awaiting dispatch to the network.
  • queued — the recipient MTN number is not yet registered with our network provider, so the order is held (not dispatched); it auto-releases to pending and is fulfilled once registration completes, usually within a short period.
  • processing — dispatched to the network and being fulfilled.
  • completed — bundle delivered successfully.
  • failed — the order could not be fulfilled.
  • refunded — the order was refunded to your wallet / original payment method.
  • Poll this endpoint after placing an order to confirm delivery.

Code Sample

cURL
curl -X GET https://kingflexygh.com/api/v1/orders/your_reference_here \
  -H "Authorization: kf_live_your_api_key_here"

4SMS API

Send bulk and transactional SMS from your own systems — OTPs, order updates, campaigns — with per-recipient delivery tracking.

Business mode required. The SMS API is available once your business (domain + description) is registered and approved on the SMS dashboard. You then send under a default sender ID from our pool — or your own sender ID after network approval (Ghana Card required). SMS credits are purchased on the credits page; 1 credit = 1 SMS segment (160 GSM chars) per recipient.
POST/api/v1/sms/send

Send an SMS to one or many recipients. Small sends (≤500 recipients) dispatch immediately and return per-send results; larger sends are queued and processed within a minute.

Request Body

{
  "message": "Your order #123 is ready. Thank you!",
  "recipients": ["0551234567", "0209876543"],
  "sender": "AcmeGH",
  "reference": "order-123"
}

Response

{
  "success": true,
  "data": {
    "campaignId": "uuid-...",
    "status": "completed",
    "recipients": 2,
    "segments": 1,
    "creditsCharged": 2,
    "sender": "AcmeGH",
    "sent": 2,
    "failed": 0,
    "balance": 498
  }
}
  • message: 3–1000 characters. Cost = SMS segments × recipients (GSM-7: 160 chars = 1 segment; unicode/emoji reduce this to 70).
  • recipients: a string or array of Ghana numbers (0XXXXXXXXX or 233XXXXXXXXX), up to 10,000 per call. Duplicates are removed automatically.
  • sender is optional — defaults to your account’s sending identity. It MUST be one of your approved sender IDs or a pool sender (call GET /sms/senders); any other value is rejected with 400. Custom senders require business mode.
  • reference is an optional idempotency key (≤100 chars): retrying with the same reference returns the original campaign instead of sending again or double-charging.
  • Credits are debited up-front; provider-rejected messages are refunded automatically when the campaign settles.
  • Content policy: telco transaction-message impersonation (fake MoMo receipts etc.) is blocked. Links to any domain are allowed for business accounts.
  • HTTP 402 = insufficient SMS credits. HTTP 403 = business mode not active or account suspended. HTTP 429 = rate limited.

Code Sample

cURL
curl -X POST https://kingflexygh.com/api/v1/sms/send \
  -H "Authorization: kf_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Your order #123 is ready for pickup. Thank you!",
    "recipients": ["0551234567", "0209876543"],
    "sender": "AcmeGH"
  }'
GET/api/v1/sms/senders

List the sender IDs this API key may send under — your approved own sender IDs plus the shared pool senders. Use these exact values for the sender field.

Response

{
  "success": true,
  "data": {
    "mode": "business",
    "defaultSender": "AcmeGH",
    "senders": [
      { "sender": "AcmeGH", "type": "own", "isDefault": true },
      { "sender": "KFT SMS", "type": "pool", "isDefault": false }
    ]
  }
}
  • type "own" = a sender ID approved for your business; "pool" = a shared platform sender any approved business may use.
  • If mode is not "business", the list is empty — register your business on the SMS dashboard to unlock custom senders.

Code Sample

cURL
curl -X GET https://kingflexygh.com/api/v1/sms/senders \
  -H "Authorization: kf_live_your_api_key_here"
GET/api/v1/sms/messages/{campaignId}

Delivery status for a send. Returns the campaign summary, a delivery rollup, and per-recipient statuses (100 per page).

Query Parameters

pagenumberoptionalZero-based page of per-recipient rows (100/page)
statusstringoptionalFilter rows: queued, sent, delivered, undelivered, failed, expired, rejected

Response

{
  "success": true,
  "data": {
    "campaign": {
      "id": "uuid-...",
      "sender_used": "AcmeGH",
      "recipients_count": 2,
      "segments": 1,
      "credits_charged": 2,
      "status": "completed",
      "created_at": "2026-..."
    },
    "delivery": { "delivered": 2 },
    "messages": [
      {
        "recipient": "233551234567",
        "status": "delivered",
        "status_updated_at": "2026-..."
      }
    ],
    "page": 0
  }
}
  • Use the campaignId returned by POST /sms/send.
  • Message statuses: queued → sent → delivered | undelivered | expired | rejected. failed = rejected by the provider at send time (refunded).
  • Delivery reports arrive asynchronously from the network — poll this endpoint a few minutes after sending for final statuses.

Code Sample

cURL
curl -X GET "https://kingflexygh.com/api/v1/sms/messages/your_campaign_id?status=delivered" \
  -H "Authorization: kf_live_your_api_key_here"
GET/api/v1/sms/balance

Your SMS credit balance and account mode.

Response

{
  "success": true,
  "data": {
    "credits": 498,
    "totalPurchased": 600,
    "totalUsed": 102,
    "mode": "business",
    "accountStatus": "active"
  }
}
  • SMS credits are separate from your GHS wallet — buy bundles at kingflexygh.com/dashboard/sms/credits.
  • Check balance before large campaigns; sends fail with HTTP 402 when credits are insufficient.

Code Sample

cURL
curl -X GET https://kingflexygh.com/api/v1/sms/balance \
  -H "Authorization: kf_live_your_api_key_here"

5Utility Bills (Commission)

Pay ECG, Ghana Water, DSTV, GOtv, or StarTimes bills at face value on behalf of your customers — and earn a share of KiNG FLEXY GH's Hubtel commission on every payment.

Separate key required. These four endpoints only accept a Commission Services key (prefix kf_cs_live_...) — a standard key is rejected with 403. The reverse is also true: a Commission Services key is rejected with 403 on every other /api/v1/* endpoint (packages, data purchases, wallet, SMS, etc.).

Generate one from Dashboard → Developer API — it requires an active shop (approved and switched on), since your commission is paid into your shop wallet. Like the standard key, it starts pending and needs admin approval before it works.

How the money moves: the bill's face value is debited from your main wallet when you call POST /pay. Once the order reaches completed, your commission_share_percent cut of the platform's commission is credited automatically to your shop wallet — withdraw it like any other shop earning.

GET/api/v1/utilities/billers

Full biller catalog for utility bill payments — including currently disabled billers, so you can build your UI without hardcoding which ones are live.

Response

{
  "success": true,
  "data": {
    "billers": [
      {
        "key": "ecg",
        "label": "ECG Prepaid & Postpaid",
        "enabled": true,
        "account_label": "Meter number",
        "requires_phone": true,
        "lookup_by": "phone",
        "links_phone_to_account": true,
        "has_amount_due": true
      },
      {
        "key": "dstv",
        "label": "DSTV",
        "enabled": true,
        "account_label": "Smartcard number",
        "requires_phone": false,
        "lookup_by": "account",
        "links_phone_to_account": false,
        "has_amount_due": true
      }
    ],
    "min_amount": 1,
    "max_amount": 1000,
    "currency": "GHS"
  }
}
  • key values are: ecg, ghana_water, dstv, gotv, startimes — pass this exact string as biller on /lookup and /pay.
  • enabled is false for a biller currently switched off by an admin — still listed so your UI can grey it out instead of guessing.
  • lookup_by tells you which field ecg needs on /lookup ("phone") vs every other biller ("account").
  • requires_phone — whether /pay requires a customer phone for this biller (ecg, ghana_water). Note: /lookup accepts account alone for ecg (phone optional there).
  • links_phone_to_account is true only for ecg — one phone can be linked to more than one meter, so always let the customer pick from the meters array /lookup returns.
  • min_amount / max_amount are the live, admin-configurable limits enforced by /pay — read them from here instead of hardcoding GHS 1–1000.

Code Sample

cURL
curl -X GET https://kingflexygh.com/api/v1/utilities/billers \
  -H "Authorization: kf_cs_live_your_commission_key_here"
GET/api/v1/utilities/lookup

Verify an account before paying. Always show your customer the returned name (or, for ECG, the linked meters) and get their confirmation before calling /pay.

Query Parameters

billerstringOne of: ecg, ghana_water, dstv, gotv, startimes
accountstringMeter/smartcard/account number, max 30 chars. Required for every biller, including ecg — for ecg pass the phone number here too if you have no separate meter number, since the query actually runs on phone.
phonestringoptionalCustomer phone, max 30 chars. Required for ghana_water. For ecg, this is what the lookup actually queries by — supply it, not just account.

Response

{
  "success": true,
  "data": {
    "account_name": "KWAME MENSAH",
    "account_number": "7041234567",
    "amount_due": 245.80,
    "bouquet": null,
    "meters": []
  }
}
  • ECG's shape differs from every other biller: account_name, account_number, amount_due and bouquet are always null — the real result is meters: [{ "name": "KWAME MENSAH", "meterNumber": "3701234567", "outstanding": 245.8 }, ...]. One phone can list several meters; let the customer choose the right one.
  • amount_due can be negative — that means the customer has a credit balance, not a bill due.
  • 404 = account/meter/smartcard not found (bad number). 502 = the billing provider is temporarily unreachable — retry shortly, do not treat as "not found".

Code Sample

cURL
# DSTV — query by smartcard number
curl -X GET "https://kingflexygh.com/api/v1/utilities/lookup?biller=dstv&account=7041234567" \
  -H "Authorization: kf_cs_live_your_commission_key_here"

# ECG — query by phone (account is still required; pass the same number)
curl -X GET "https://kingflexygh.com/api/v1/utilities/lookup?biller=ecg&phone=0551617309&account=0551617309" \
  -H "Authorization: kf_cs_live_your_commission_key_here"

reference on /pay is a pure idempotency key, not a distinct-payment key. Reusing the same reference — even with a different biller, account, or amount — returns the details of the ORIGINAL order and never charges you again; it does not re-validate against the new values you sent. Use a unique reference for every distinct bill. Reuse the same reference ONLY to safely retry the exact same payment (e.g. after a network timeout).

POST/api/v1/utilities/pay

Pay a bill at face value from your wallet. Auto-dispatches to the biller in the background — poll GET /orders/{reference} for the final status.

Request Body

{
  "biller": "dstv",
  "account": "7041234567",
  "amount": 65.00,
  "reference": "bill_dstv_7041234567_01"
}

Response

{
  "success": true,
  "data": {
    "reference": "UTIL-DSTV-3f9a2b1c4d5e6f70",
    "order_id": "uuid-...",
    "status": "pending",
    "biller": "dstv",
    "account": "7041234567",
    "amount": 65.00,
    "commission_share_percent": 40,
    "new_balance": 435.00
  }
}
  • reference is a pure idempotency key — see the callout above. It is optional, 1–64 chars of letters, numbers, dot, underscore or hyphen.
  • Save the reference from the RESPONSE, not the one you sent — it is our own generated code (UTIL-<BILLER>-<random>) and is what GET /orders/{reference} expects.
  • On an idempotent replay (reused reference), the response is smaller: { reference, order_id, status, already_processed: true } — no biller/account/amount/commission_share_percent/new_balance, since nothing new happened.
  • phone is required for ecg and ghana_water (omit for dstv/gotv/startimes). For ecg, account is the specific meter number from the /lookup meters array — not the phone.
  • amount must be within the live min_amount/max_amount from GET /billers (defaults GHS 1.00–1000.00).
  • Without a reference, sending the same biller + account + amount twice within 30 seconds is rejected with 409. If your first request timed out, reuse that request's original reference — you'll get the original order back via idempotent replay. A new reference does not bypass the 30-second window; genuinely distinct same-amount payments to the same account must wait it out.
  • commission_share_percent is your cut of the platform commission (admin-configurable) — it is credited to your shop wallet once the order completes, not at response time.

Code Sample

cURL
# DSTV — account-only biller
curl -X POST https://kingflexygh.com/api/v1/utilities/pay \
  -H "Authorization: kf_cs_live_your_commission_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "biller": "dstv",
    "account": "7041234567",
    "amount": 65.00,
    "reference": "bill_dstv_7041234567_01"
  }'

# ECG — account is the METER (from lookup meters[]), phone is required too
curl -X POST https://kingflexygh.com/api/v1/utilities/pay \
  -H "Authorization: kf_cs_live_your_commission_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "biller": "ecg",
    "account": "3701234567",
    "phone": "0551617309",
    "amount": 50.00,
    "reference": "bill_ecg_3701234567_01"
  }'
GET/api/v1/utilities/orders/{reference}

Poll the fulfillment status of a utility bill order using the reference from the /pay response. Only returns orders that belong to your own account.

Response

{
  "success": true,
  "data": {
    "reference": "UTIL-DSTV-3f9a2b1c4d5e6f70",
    "status": "completed",
    "payment_status": "paid",
    "biller": "dstv",
    "account_number": "7041234567",
    "account_name": "KWAME MENSAH",
    "amount": 65.00,
    "commission_earned": 3.64,
    "created_at": "2026-...",
    "updated_at": "2026-..."
  }
}
  • Status flow: pending → processing → completed | failed | refunded.
  • The account field here is called account_number — not account as in the /pay request body. Same value, different key name across endpoints.
  • commission_earned is null until the order reaches completed — it is your realized share of the commission, credited to your shop wallet at that point.
  • Poll every few seconds after /pay until status leaves pending / processing.

Code Sample

cURL
curl -X GET https://kingflexygh.com/api/v1/utilities/orders/UTIL-DSTV-3f9a2b1c4d5e6f70 \
  -H "Authorization: kf_cs_live_your_commission_key_here"

Rate Limits (per key)

EndpointLimit
GET /billers30 / min
GET /lookup10 / min
POST /pay6 / min
GET /orders/{reference}30 / min

Error Codes (this section)

CodeWhen it occurs
400Invalid biller/account/phone/amount/reference, or insufficient wallet balance
401Missing or invalid API key
403Wrong key type (commission key required here; standard key required everywhere else), key pending/revoked, or account suspended
404Account/meter/smartcard not found (lookup), or order not found (status)
409Duplicate order — same biller + account + amount resent within 30s without a reference
429Rate limit exceeded — see limits above
502Billing provider temporarily unreachable — retry shortly (lookup only)
503Utility bills, or this specific biller, currently disabled by an admin

6Supported Networks

Network ValueProviderNotes
"MTN"MTN GhanaMost widely available bundles
"Telecel"Telecel Ghana (formerly Vodafone)
"AT-iShare"AirtelTigo iShareAirtelTigo bundle type 1
"AT-BigTime"AirtelTigo BigTimeAirtelTigo bundle type 2
Network values are case-sensitive. Use GET /packages to see exactly which networks and sizes are currently available.

7Error Codes

CodeWhen it occurs
400Bad request — invalid phone, volume_gb, network value, or malformed body
401Missing or invalid API key
403Key pending approval, revoked, suspended account, or role not allowed
404Package or order not found for the given network/size/reference
409Duplicate reference — an order with this reference already exists
429Rate limit exceeded — back off and retry after a short delay
500Internal server error — contact support if persistent
503API feature temporarily disabled by administrator

8Full Examples

Complete runnable data purchase example. Select your language.

cURL
curl -X POST https://kingflexygh.com/api/v1/data/purchase \
  -H "Authorization: kf_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "network": "MTN",
    "volume_gb": 5,
    "recipient": "0551617309",
    "reference": "order_001"
  }'

Ready to start building?

© 2026 KiNG FLEXY TECHNOLOGIES LTD · Need help? Contact support via your dashboard.