⚡ Disco Electricity Vending
Purchase prepaid tokens or pay postpaid bills for any supported distribution company meter. Disco vending is its own API collection — no Venshack meter registration is required, and it is separate from Vending (Venshack).
Use /v1/vending/* for meters registered to your Venshack
organization, and /v1/disco-vending/* for any supported
DISCO meter. The two collections are independent; nothing in the
existing Venshack vending API has changed.
Supported DISCOs
| Code | Distribution company |
|---|---|
IKEJA | Ikeja Electric |
EKO | Eko Electricity Distribution |
ABUJA | AEDC |
KANO | Kano Electricity Distribution |
PH | Port Harcourt Electricity Distribution |
JOS | Jos Electricity Distribution |
KADUNA | Kaduna Electric |
ENUGU | Enugu Electricity Distribution |
IBADAN | Ibadan Electricity Distribution |
BENIN | Benin Electricity Distribution |
ABA | Aba Power |
YOLA | Yola Electricity Distribution |
Common utility aliases such as IKEDC, EKEDC,
AEDC and PHEDC are accepted and normalized to
their canonical codes.
Pricing
| Operation | Cost |
|---|---|
| Validate meter | Free |
| Purchase token / pay bill | ₦50 flat (under ₦10,000) · 0.5% above |
| Requery a pending transaction | Free |
| List transactions | Free |
| Query token details | Free |
How It Works
- Validate meter → Confirm the meter and get the customer name
- Confirm with user → Show the customer name before purchase
- Purchase → Charge your wallet and receive the token, or a pending reference
- Requery → If the transaction is pending, requery the reference until it resolves
Step 1: Validate Meter
Always validate first to confirm the meter and show the customer name.
{
"meterNumber": "1234567890123",
"disco": "IKEJA",
"meterCategory": "PREPAID"
}
{
"success": true,
"data": {
"success": true,
"meterNumber": "1234567890123",
"customerName": "John Doe",
"meterType": "PREPAID",
"disco": "IKEJA",
"meterCategory": "PREPAID",
"message": "Meter validated successfully"
}
}
Step 2: Purchase Token / Pay Bill
Purchase electricity for the validated meter. Costs ₦50 for amounts under ₦10,000, 0.5% above.
{
"meterNumber": "1234567890123",
"amount": 50000, // Amount in kobo (50000 = ₦500)
"disco": "IKEJA",
"meterCategory": "PREPAID",
"phone": "08012345678", // Optional but recommended
"externalRef": "my-order-123" // Optional - your reference
}
{
"success": true,
"data": {
"success": true,
"token": "1234-5678-9012-3456-7890",
"units": 25.5,
"meterNumber": "1234567890123",
"amount": 50000,
"reference": "202603231430abc123",
"customerName": "John Doe",
"disco": "IKEJA",
"meterCategory": "PREPAID",
"message": "Token purchased successfully"
}
}
DISCO purchases are not always delivered immediately. When the provider is
still processing, the response is HTTP 200 with
success: false, errorCode: "PENDING" and a
reference. Do not retry the purchase with a new reference —
requery the existing one instead.
{
"success": true,
"data": {
"success": false,
"meterNumber": "1234567890123",
"amount": 50000,
"reference": "202603231430abc123",
"errorCode": "PENDING",
"disco": "IKEJA",
"meterCategory": "PREPAID",
"message": "Transaction is being processed. Use the reference to requery for the final status."
}
}
Step 3: Requery a Pending Transaction
Pass the reference from the original purchase. Requery is free
and safe to call repeatedly.
{
"reference": "202603231430abc123"
}
The response uses the same shape as a purchase: a delivered transaction
returns the token, while a still-processing one returns
errorCode: "PENDING" again.
Postpaid Meters
Set meterCategory to POSTPAID to pay a postpaid
bill. There is no token for postpaid payments; a successful response
returns the payment reference and
message: "Payment completed successfully".
Request Fields
| Field | Required | Description |
|---|---|---|
meterNumber |
Yes | 11-13 digit meter number |
disco |
Yes | DISCO code (e.g. IKEJA) or a supported alias |
meterCategory |
No | PREPAID (default) or POSTPAID |
amount |
Yes (purchase) | Amount in kobo (100 kobo = ₦1). Range: 20000-50000000 (₦200-₦500,000) |
phone |
No | Customer phone number; recommended |
externalRef |
No | Your reference ID for tracking |
Sandbox Test Cases
TEST API keys (vk_test_) return deterministic sandbox values
and never call a live electricity provider.
| Meter number | Validate | Purchase |
|---|---|---|
00000000001 |
success: false (INVALID_METER) |
success: false (INVALID_METER) |
00000000002 |
Valid customer | errorCode: "PENDING" |
| Any other 11-13 digit number | Valid customer | Token generated |
Amounts below 50000 kobo (₦500) fail with MIN_AMOUNT in
sandbox. Requery resolves any sandbox PENDING reference
successfully. Sandbox requests are free but still appear in your API call
logs; webhooks are not sent for TEST calls.
Code Example
const API_KEY = 'vk_prod_xxxxxxxxxxxxx';
const BASE_URL = 'https://api-developers.venshack.io/v1';
async function purchaseDiscoElectricity({
meterNumber,
amountInKobo,
disco, // e.g. 'IKEJA'
meterCategory, // 'PREPAID' | 'POSTPAID'
phone
}) {
// Step 1: Validate meter
const validateRes = await fetch(`${BASE_URL}/disco-vending/validate`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ meterNumber, disco, meterCategory })
});
const meter = await validateRes.json();
if (!meter.success) {
throw new Error(meter.error.message);
}
console.log(`Customer: ${meter.data.customerName}`);
// Step 2: Purchase
const purchaseRes = await fetch(`${BASE_URL}/disco-vending/purchase`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
meterNumber,
amount: amountInKobo,
disco,
meterCategory,
...(phone ? { phone } : {}),
externalRef: `order-${Date.now()}`
})
});
let result = await purchaseRes.json();
// Step 3: Pending transactions are resolved by requery
if (result.data?.errorCode === 'PENDING') {
const reference = result.data.reference;
for (let attempt = 0; attempt < 3; attempt++) {
await new Promise((resolve) => setTimeout(resolve, 2000));
const requeryRes = await fetch(`${BASE_URL}/disco-vending/requery`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ reference })
});
result = await requeryRes.json();
if (result.data?.errorCode !== 'PENDING') break;
}
}
if (result.data?.success) {
console.log(`Token: ${result.data.token}`);
console.log(`Units: ${result.data.units} kWh`);
return result.data;
}
throw new Error(result.data?.message || result.error?.message);
}
// 50000 kobo = ₦500
purchaseDiscoElectricity({
meterNumber: '1234567890123',
amountInKobo: 50000,
disco: 'IKEJA',
meterCategory: 'PREPAID',
phone: '08012345678'
});
Transaction History
List DISCO vending transactions for your organization. Transactions include
disco, meterCategory and reference
fields.
GET /v1/disco-vending/transactions?page=1&limit=20&meterNumber=1234567890123
Query Token
{
"token": "12345678901234567890"
}
Webhooks
DISCO vending emits the same vending.completed and
vending.failed events as Venshack vending, with
meterType: "DISCO" plus disco and
meterCategory in the payload. Pending transactions do not
emit vending.failed; they emit
vending.completed once requery confirms delivery. See the
Webhooks Guide for how to receive and
verify webhook events.
Error Handling
| Error Code | Description |
|---|---|
PENDING |
Transaction is still processing — requery with the reference |
INVALID_METER |
Meter number not found or invalid |
INVALID_DISCO |
Unsupported or missing disco code |
INVALID_AMOUNT |
Amount is not supported for this meter |
INVALID_SERVICE |
The DISCO service is currently unavailable |
PROVIDER_UNAVAILABLE |
Electricity provider is temporarily unavailable — try again later |
DUPLICATE_REQUEST |
A transaction with this reference already exists |
TRANSACTION_NOT_FOUND |
The reference could not be found |
TRANSACTION_FAILED |
The provider rejected the transaction |
TIMEOUT |
Provider did not respond in time — requery before retrying |
NETWORK_ERROR |
Could not reach the electricity provider |
PAYMENT_REQUIRED |
Insufficient wallet balance |
Never retry a PENDING or TIMEOUT purchase with a
new reference — requery the original reference first to avoid
double vending.