API Documentation

Home / API Documentation

API Documentation

Use this API to place orders, check order status, list services, and check balance.
Quick Start
  1. Open your dashboard → Developer Portal and create an API key.
  2. If API access is not active, purchase an API access plan (KYC may be required) and wait for admin approval.
  3. Store the key server-side (ENV/secret manager). Never expose it in frontend JS.
  4. Call the API with HTTPS from your backend server.
  5. Use action=services to fetch valid service IDs, min/max, and rate.
  6. Place orders with action=add, then poll with action=status.
Base URL
https://rukkyhub.com/api/v1
HTTP Method: POST | Response: JSON
Authentication
Your API key is like a password. Keep it secret.
You can send the key in the request body (key=...) or as a header (recommended).
X-API-KEY: YOUR_API_KEY
key=YOUR_API_KEY
If you revoke a key, it stops working immediately.
Security Notes
  • Use HTTPS only. Do not send API keys over plain HTTP in production.
  • Use scoped API keys to limit allowed actions (services/add/status/balance).
  • Requests are rate-limited to reduce abuse and brute forcing.
  • You can restrict keys to IPs/domains using the whitelist feature in Developer Portal.
  • If you enforce a Domain whitelist, send X-API-ORIGIN / Origin header (example: https://example.com). If you cannot set headers, send origin=https://example.com or domain=example.com in the request body.
  • Order status can only be fetched for orders that belong to your account.
Pricing & Discounts
  • SMM: action=services returns rates already adjusted by your plan SMM discount.
  • VTU: pricing uses the configured VTU base + profit. VTU API discounts are configured per plan and per VTU category (airtime/data/SME/cable/electricity/education/recharge card). Discounts reduce only the profit portion (never below base cost).
  • Admin: SMM discount is set inside API Access Plans. VTU reseller discounts are set in Global Settings per plan.
Actions
Action Description Required Fields
servicesList all serviceskey, action
addPlace a new orderkey, action, service, link, quantity
add_bulkPlace multiple orders in one requestkey, action, orders[]
statusGet order statuskey, action, order
balanceGet account balancekey, action
vtu_data_plansList VTU data planskey, action, service_id
vtu_sme_plansList VTU SME planskey, action, network
vtu_cable_plansList VTU cable planskey, action, service_id
vtu_electric_discosList VTU electricity discoskey, action
vtu_cable_verifyVerify cable smartcardkey, action, service_id, customer_id
vtu_electricity_verifyVerify electricity meterkey, action, service_name, meter_type, meter_number
vtu_airtimeBuy airtimekey, action, service_name, phone, amount, pin
vtu_dataBuy datakey, action, plan_id, phone, pin
vtu_smeBuy SME datakey, action, plan_id, phone, pin
vtu_cableSubscribe cablekey, action, plan_id, customer_id, phone, pin
vtu_electricityBuy electricitykey, action, service_name, meter_type, meter_number, phone, amount, pin
vtu_educationBuy education pin (WAEC)key, action, phone, amount, pin
vtu_recharge_cardPrint recharge cardkey, action, card_network, value, quantity, pin
vtu_statusGet VTU transaction statuskey, action, trx
Order Status Values
pending processing completed cancelled refunded partial
Status mapping: pending(0), processing(1), completed(2), cancelled(3), refunded(4), partial(5).
Examples
cURL: services
curl -X POST "https://rukkyhub.com/api/v1" -H "X-API-KEY: YOUR_API_KEY" -d "action=services"
cURL: services (Domain whitelist enabled)
curl -X POST "https://rukkyhub.com/api/v1" -H "X-API-KEY: YOUR_API_KEY" -H "X-API-ORIGIN: https://example.com" -d "action=services"
cURL: add order
curl -X POST "https://rukkyhub.com/api/v1" -H "X-API-KEY: YOUR_API_KEY" -d "action=add&service=123&link=https://example.com&quantity=1000"
cURL: bulk orders
curl -X POST "https://rukkyhub.com/api/v1" -H "X-API-KEY: YOUR_API_KEY" -d 'action=add_bulk&orders=[{"service":123,"link":"https://example.com","quantity":1000},{"service":124,"link":"https://example.com/2","quantity":500}]'
cURL: order status
curl -X POST "https://rukkyhub.com/api/v1" -H "X-API-KEY: YOUR_API_KEY" -d "action=status&order=4488"
cURL: balance
curl -X POST "https://rukkyhub.com/api/v1" -H "X-API-KEY: YOUR_API_KEY" -d "action=balance"
cURL: VTU data plans
curl -X POST "https://rukkyhub.com/api/v1" -H "X-API-KEY: YOUR_API_KEY" -d "action=vtu_data_plans&service_id=mtn-data"
cURL: VTU buy data
curl -X POST "https://rukkyhub.com/api/v1" -H "X-API-KEY: YOUR_API_KEY" -d "action=vtu_data&plan_id=1&phone=08012345678&pin=1234"
cURL: VTU status
curl -X POST "https://rukkyhub.com/api/v1" -H "X-API-KEY: YOUR_API_KEY" -d "action=vtu_status&trx=XXXX"
PHP Example File
https://rukkyhub.com/assets/php_api_example.txt
Good vs Bad Integration
Bad Example (Do NOT do this)
Never expose your API key in frontend JavaScript or public HTML.
<script>
fetch("https://rukkyhub.com/api/v1", {
  method: "POST",
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
  body: "action=services&key=YOUR_API_KEY"
}).then(r => r.json()).then(console.log);
</script>
Good Example (Backend PHP using cURL + header)
<?php
$apiUrl = "https://rukkyhub.com/api/v1";
$apiKey = getenv("SMM_API_KEY");
$apiOrigin = getenv("SMM_API_ORIGIN");

$ch = curl_init($apiUrl);
$headers = [
  "X-API-KEY: {$apiKey}",
  "Accept: application/json",
];
if (!empty($apiOrigin)) {
  $headers[] = "X-API-ORIGIN: {$apiOrigin}";
}
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_POSTFIELDS => http_build_query(["action" => "services"]),
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CONNECTTIMEOUT => 10,
  CURLOPT_TIMEOUT => 20,
  CURLOPT_HTTPHEADER => $headers,
]);
$raw = curl_exec($ch);
$http = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($raw === false) { throw new Exception(curl_error($ch)); }
curl_close($ch);

$data = json_decode($raw, true);
if (!is_array($data)) { throw new Exception("Invalid JSON"); }
if ($http >= 400 || isset($data["error"]) || isset($data["errors"])) { throw new Exception($raw); }
print_r($data);
Good Example (Server-side Node.js fetch)
const apiUrl = "https://rukkyhub.com/api/v1";
const apiKey = process.env.SMM_API_KEY;

const params = new URLSearchParams({ action: "services" });
const res = await fetch(apiUrl, {
  method: "POST",
  headers: {
    "X-API-KEY": apiKey,
    "Content-Type": "application/x-www-form-urlencoded",
    "Accept": "application/json"
  },
  body: params
});
const data = await res.json();
if (!res.ok || data.error || data.errors) throw new Error(JSON.stringify(data));
console.log(data);
Error Handling
  • 429 Rate limit: backoff and retry later (do not spam).
  • 403 Forbidden: API access inactive, key restricted by whitelist, or action not allowed by scope/plan.
  • 422 Validation: check required fields (service/link/quantity/pin) and retry with correct data.
  • 500 Server error: check response message, then retry later.
VTU Quick Start
  1. Create an API key in the Developer Portal. Enable the needed VTU scopes (vtu_data_plans, vtu_data, vtu_status, etc.).
  2. Fetch plans using vtu_data_plans / vtu_sme_plans / vtu_cable_plans.
  3. Purchase using vtu_data / vtu_sme / vtu_cable / vtu_airtime / vtu_electricity.
  4. Use vtu_status to check the transaction status by trx.
  5. Optionally enable webhooks (vtu.success / vtu.failed) for auto callbacks.
VTU Responses
VTU purchase endpoints return a consistent response.
{
  "status": "success|failed|processing|pending",
  "category": "data|sme|airtime|cable|electricity|education|recharge_card",
  "trx": "TRX_STRING",
  "provider_ref": "REFERENCE_IF_ANY",
  "amount": "123.45",
  "balance": "1000.00",
  "currency": "NGN",
  "message": "optional error/success message",
  "cards": [ { "pin": "...", "serial": "..." } ]
}
Webhooks (Callbacks)
Create a webhook in Developer Portal and subscribe to events. Webhooks are delivered asynchronously with retries.
Headers sent to your webhook URL:
X-Webhook-Event: vtu.success
X-Webhook-Signature: <hmac_sha256(payload_json, webhook_secret)>
Supported events:
vtu.status_changed
vtu.processing
vtu.success
vtu.failed
order.created
order.status_changed
order.refunded
deposit.success
withdraw.approved
Example payload:
{
  "event": "vtu.success",
  "occurred_at": "2026-04-05T12:00:00Z",
  "vtu": {
    "id": 1,
    "trx": "TRX_STRING",
    "category": "data",
    "service_name": "mtn-data",
    "phone": "08012345678",
    "amount": 123.45,
    "base_amount": 120.00,
    "profit_amount": 3.45,
    "provider": "strowallet",
    "provider_ref": "ABC123",
    "status": "success",
    "meta": {},
    "created_at": "2026-04-05T12:00:00Z",
    "updated_at": "2026-04-05T12:00:05Z"
  }
}
Webhook Verification (Good Example)
Always verify X-Webhook-Signature with your webhook secret before trusting the payload.
<?php
// Example webhook receiver (plain PHP)
$secret = getenv("SMM_WEBHOOK_SECRET");
$payload = file_get_contents("php://input");
$signature = $_SERVER["HTTP_X_WEBHOOK_SIGNATURE"] ?? "";

$expected = hash_hmac("sha256", $payload, $secret);
if (!hash_equals($expected, $signature)) {
  http_response_code(401);
  exit("Invalid signature");
}

http_response_code(200);
echo "OK";
// Process the JSON asynchronously (queue/job) to avoid timeouts.
Node.js (Express)
import crypto from "crypto";
import express from "express";

const app = express();
app.post("/webhook", express.raw({ type: "*/*" }), (req, res) => {
  const secret = process.env.SMM_WEBHOOK_SECRET;
  const payload = req.body.toString("utf8");
  const signature = req.header("X-Webhook-Signature") || "";

  const expected = crypto.createHmac("sha256", secret).update(payload).digest("hex");
  if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))) {
    return res.status(401).send("Invalid signature");
  }
  return res.status(200).send("OK");
});
Common Errors
  • Invalid api key: key is wrong or revoked.
  • This API key is not allowed for this action: your key scope does not include the requested action.
  • Please follow the limit: quantity outside min/max range.
  • Insufficient balance: not enough funds or minimum balance would be violated.

Rukkyhub processes personal data only to provide services, ensure security, and meet legal requirements. We do not sell user data. By using this site, you consent to our data processing in accordance with GDPR. learn more

Allow