NEW APP AVAILABLE FOR DOWNLOAD NOW

Get it on Google PlayDownload on the App Store

Electricity

Pay electricity bills for all major distribution companies

Pay prepaid and postpaid electricity bills for all major Nigerian distribution companies.

Supported Distributors

CodeNameRegion
IKEDCIkeja ElectricLagos (Ikeja)
EKEDCEko ElectricLagos (Eko)
AEDCAbuja ElectricAbuja
KEDCKaduna ElectricKaduna
JEDCJos ElectricJos
IBEDCIbadan ElectricIbadan
KAEDCKano ElectricKano
EEDCEnugu ElectricEnugu
PhEDPort Harcourt ElectricPort Harcourt
BEDCBenin ElectricBenin
ABAAba PowerAba
YEDCYola ElectricYola

Purchase Flow

Electricity purchases require a two-step process:

  1. Verify - Validate the meter number and get customer details
  2. Purchase - Make the payment

This prevents payments to invalid meters.

Step 1: List Products

bash
curl -X GET \
  -H "Authorization: Bearer sk_live_your_secret_key" \
  "https://my.rizpay.app/api/partners/v1/products/electricity?distributor=IKEDC"

Response:

json
{
  "status": { "code": 200, "message": "Success" },
  "data": [
    {
      "id": "prd_8152",
      "type": "electricity",
      "attributes": {
        "display_name": "Ikeja Electric Payment - IKEDC",
        "distributor": "Ikeja Electric Payment - IKEDC",
        "meter_type": null,
        "min_amount": "100.0",
        "max_amount": "100000.0",
        "price": {
          "currency": "NGN",
          "basis": "face_value",
          "min_amount": "100.00",
          "max_amount": "100000.00"
        }
      }
    }
  ],
  "pagination": {
    "page": 1,
    "per_page": 20,
    "total_pages": 1,
    "total_count": 12
  }
}

Product ids are numeric with a prd_ prefix (e.g. prd_8152). There is one product per distribution company. meter_type on the product is null: you supply the meter type (prepaid or postpaid) on the purchase request, and verify returns the meter type it detected.

The price block

Electricity is variable: the partner chooses the amount. RizPay returns the supported range as a face_value tuple. You'll be billed exactly the amount you submit on the purchase request.

Step 2: Verify Meter

Required before purchase. Validates the meter and returns customer details.

bash
curl -X POST \
  -H "Authorization: Bearer sk_live_your_secret_key" \
  -H "Content-Type: application/json" \
  -d '{
    "product_id": "prd_8152",
    "meter_number": "12345678901",
    "meter_type": "prepaid"
  }' \
  https://my.rizpay.app/api/partners/v1/purchases/verify

Response:

json
{
  "status": { "code": 200, "message": "Verification successful" },
  "data": {
    "verified": true,
    "product_id": "prd_8152",
    "product_type": "electricity",
    "price": {
      "currency": "NGN",
      "basis": "face_value",
      "min_amount": "100.00",
      "max_amount": "100000.00"
    },
    "customer": {
      "meter_number": "12345678901",
      "meter_type": "prepaid",
      "customer_name": "JOHN DOE",
      "address": "123 Main Street, Ikeja, Lagos",
      "distributor": "Ikeja Electric Payment - IKEDC"
    }
  }
}

The price block on verify gives you the supported amount range for the verified meter so you can prompt your end-user before submitting the purchase.

Verification Errors

If the meter number cannot be validated, verify returns a 400 with error.code set to VALIDATION_ERROR and a message describing the problem. If the distributor itself is unavailable, purchases for that product return PRODUCT_UNAVAILABLE.

ErrorMeaning
VALIDATION_ERRORMeter number could not be verified
PRODUCT_UNAVAILABLEDistributor service is down

Step 3: Make Purchase

After verification, make the purchase. Include the meter_type (prepaid or postpaid) you verified:

bash
curl -X POST \
  -H "Authorization: Bearer sk_live_your_secret_key" \
  -H "Content-Type: application/json" \
  -d '{
    "product_id": "prd_8152",
    "meter_number": "12345678901",
    "meter_type": "prepaid",
    "amount": "5000.00",
    "phone_number": "08012345678",
    "external_reference": "1736234400D4E5F6"
  }' \
  https://my.rizpay.app/api/partners/v1/purchases

Response:

json
{
  "status": { "code": 201, "message": "Purchase created successfully" },
  "data": {
    "id": "txn_abc123",
    "type": "transaction",
    "attributes": {
      "amount": "5000.0",
      "currency": "NGN",
      "status": "pending",
      "category": "purchase",
      "description": "Purchase of IKEDC Electricity",
      "reference": "elec0order0001abcd",
      "external_reference": "1736234400D4E5F6",
      "product_type": "electricity",
      "phone_number": "08012345678",
      "meter_number": "12345678901",
      "price": {
        "product_amount": "5000.00",
        "fee_amount": "0.00",
        "total_debit": "5000.00",
        "currency": "NGN",
        "basis": "face_value"
      },
      "created_at": "2026-05-18T10:30:00+01:00",
      "updated_at": "2026-05-18T10:30:00+01:00"
    }
  }
}

The price breakdown

Same shape as airtime. basis is face_value because the partner picked the amount.

Successful Purchase

Poll the transaction (or use webhooks) until status reaches successful. The completed purchase uses the same nested shape as the create response. For a prepaid meter the recharge token appears inside data.attributes.token:

json
{
  "status": { "code": 200, "message": "Purchase details retrieved" },
  "data": {
    "id": "txn_abc123",
    "type": "transaction",
    "attributes": {
      "amount": "5000.0",
      "currency": "NGN",
      "status": "successful",
      "category": "purchase",
      "description": "Purchase of IKEDC Electricity",
      "reference": "elec0order0001abcd",
      "external_reference": "1736234400D4E5F6",
      "product_type": "electricity",
      "phone_number": "08012345678",
      "meter_number": "12345678901",
      "token": "1234-5678-9012-3456-7890",
      "price": {
        "product_amount": "5000.00",
        "fee_amount": "0.00",
        "total_debit": "5000.00",
        "currency": "NGN",
        "basis": "face_value"
      },
      "created_at": "2026-05-18T10:30:00+01:00",
      "updated_at": "2026-05-18T10:30:05+01:00"
    }
  }
}

Important: For prepaid meters, provide the token to the customer. They'll enter it into their meter to load the units. The token field is present only once the purchase is successful and only for prepaid meters. There is no separate completion timestamp: use updated_at.

Complete Example

javascript
// Generate external reference: 10-digit timestamp + 6 alphanumeric
function generateReference() {
  const timestamp = Math.floor(Date.now() / 1000);
  const chars =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  let suffix = "";
  for (let i = 0; i < 6; i++) {
    suffix += chars.charAt(Math.floor(Math.random() * chars.length));
  }
  return `${timestamp}${suffix}`;
}

async function payElectricity(meterNumber, meterType, amount, phoneNumber) {
  const API_KEY = "sk_live_your_secret_key";
  const BASE_URL = "https://my.rizpay.app/api/partners/v1";

  // Step 1: Find the product (one per distributor)
  const productsRes = await fetch(
    `${BASE_URL}/products/electricity?distributor=IKEDC`,
    { headers: { Authorization: `Bearer ${API_KEY}` } }
  );
  const products = await productsRes.json();
  const product = products.data[0];

  // Step 2: Verify meter
  const verifyRes = await fetch(`${BASE_URL}/purchases/verify`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      product_id: product.id,
      meter_number: meterNumber,
      meter_type: meterType,
    }),
  });

  const verification = await verifyRes.json();
  if (!verification.data.verified) {
    throw new Error("Invalid meter number");
  }

  // Step 3: Make purchase
  const purchaseRes = await fetch(`${BASE_URL}/purchases`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      product_id: product.id,
      meter_number: meterNumber,
      meter_type: meterType,
      amount: amount,
      phone_number: phoneNumber,
      external_reference: generateReference(),
    }),
  });

  return await purchaseRes.json();
}

Meter Types

TypeDescriptionToken
prepaidPay before useYes - customer enters token
postpaidPay after useNo - payment credits account

Required Scope

Requires the purchase_electricity scope on your API key.

Next Steps

  • Cable TV - Subscribe to cable TV
  • Webhooks - Get notified when payment completes