> ## Documentation Index
> Fetch the complete documentation index at: https://docs.monei.cc/llms.txt
> Use this file to discover all available pages before exploring further.

# Payments

> Make bill payments from your Monei wallet

## Overview

Pay bills instantly from your Monei wallet. This guide covers making payments, tracking status, and handling different payment scenarios.

**What you'll learn:**

* Make bill payments
* Track payment status
* Handle payment responses
* Retry failed payments
* Best practices

***

## Make Payment

Pay a bill after validating customer details.

<CodeGroup>
  ```javascript Node.js theme={null}
  import MoneiSDK from 'monei-sdk';

  const monei = new MoneiSDK({
    apiKey: process.env.MONEI_API_KEY,
  });

  // Pay MTN airtime
  const payment = await monei.billsPay.buyElectricity({
    billerId: 'mtn-ng',
    customerId: '08012345678',
    amount: 1000,
    type: 'PREPAID'
  });

  console.log('Payment Successful!');
  console.log('Reference:', payment.reference);
  console.log('Status:', payment.status);
  console.log('Amount:', payment.amount);
  console.log('Fee:', payment.fee);
  console.log('Total Paid:', payment.totalAmount);
  console.log('Customer:', payment.customerName);
  console.log('Biller:', payment.billerName);
  ```

  ```python Python theme={null}
  from monei import MoneiClient

  monei = MoneiClient(
      api_key=os.getenv('MONEI_API_KEY')
  )

  # Make payment
  payment = monei.bills_pay.buy_electricity(
      biller_id='mtn-ng',
      customer_id='08012345678',
      amount=1000,
      type='PREPAID'
  )

  print('Payment Successful!')
  print(f'Reference: {payment.reference}')
  print(f'Status: {payment.status}')
  print(f'Amount: ₦{payment.amount}')
  print(f'Fee: ₦{payment.fee}')
  print(f'Total: ₦{payment.total_amount}')
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.monei.cc/api/v1/bills/pay \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "billerId": "mtn-ng",
      "customerId": "08012345678",
      "amount": 1000,
      "type": "PREPAID"
    }'
  ```
</CodeGroup>

**Request Parameters:**

| Parameter    | Type   | Required | Description                                       |
| ------------ | ------ | -------- | ------------------------------------------------- |
| `billerId`   | string | Yes      | Biller identifier                                 |
| `customerId` | string | Yes      | Customer ID (phone, meter, smartcard)             |
| `amount`     | number | Yes      | Payment amount                                    |
| `type`       | string | Yes      | PREPAID or POSTPAID                               |
| `reference`  | string | No       | Custom reference (auto-generated if not provided) |

**Response:**

```json theme={null}
{
  "statusCode": 200,
  "message": "Payment successful",
  "data": {
    "reference": "BILL-ABC123XYZ",
    "status": "successful",
    "amount": 1000,
    "fee": 0,
    "totalAmount": 1000,
    "customerName": "JOHN DOE",
    "customerId": "08012345678",
    "billerName": "MTN Nigeria",
    "billerId": "mtn-ng",
    "type": "PREPAID",
    "createdAt": "2024-02-15T10:30:00Z"
  }
}
```

***

## Complete Payment Flow

<CodeGroup>
  ```javascript Node.js theme={null}
  async function completeBillPayment(billerId, customerId, amount) {
    try {
      // 1. Validate customer
      console.log('Step 1: Validating customer...');
      const validation = await monei.billsValidation.validate({
        billerId: billerId,
        customerId: customerId,
        type: 'PREPAID'
      });
      
      console.log('✓ Customer validated:', validation.customerName);
      
      // 2. Check wallet balance
      console.log('\nStep 2: Checking balance...');
      const wallet = await monei.wallet.getWallet();
      const balance = parseFloat(wallet.nairaBalance);
      
      if (balance < amount) {
        throw new Error(`Insufficient balance. Have: ₦${balance}, Need: ₦${amount}`);
      }
      
      console.log('✓ Sufficient balance:', balance);
      
      // 3. Confirm payment details
      console.log('\nPayment Summary:');
      console.log('Biller:', validation.billerName);
      console.log('Customer:', validation.customerName);
      console.log('Amount: ₦' + amount);
      
      // 4. Make payment
      console.log('\nStep 3: Processing payment...');
      const payment = await monei.billsPay.buyElectricity({
        billerId: billerId,
        customerId: customerId,
        amount: amount,
        type: 'PREPAID'
      });
      
      console.log('\n✓ Payment successful!');
      console.log('Reference:', payment.reference);
      console.log('Status:', payment.status);
      console.log('Total Paid: ₦' + payment.totalAmount);
      
      return payment;
      
    } catch (error) {
      console.error('Payment failed:', error.message);
      throw error;
    }
  }

  // Usage
  await completeBillPayment('mtn-ng', '08012345678', 1000);
  ```

  ```python Python theme={null}
  async def complete_bill_payment(biller_id, customer_id, amount):
      try:
          # 1. Validate
          print('Step 1: Validating...')
          validation = monei.bills_validation.validate(
              biller_id=biller_id,
              customer_id=customer_id,
              type='PREPAID'
          )
          
          print(f'✓ Validated: {validation.customer_name}')
          
          # 2. Check balance
          print('\nStep 2: Checking balance...')
          wallet = monei.wallet.getWallet()
          balance = float(wallet.nairaBalance)
          
          if balance < amount:
              raise Exception(f'Insufficient balance')
          
          print(f'✓ Balance: ₦{balance}')
          
          # 3. Summary
          print('\nPayment Summary:')
          print(f'Biller: {validation.biller_name}')
          print(f'Customer: {validation.customer_name}')
          print(f'Amount: ₦{amount}')
          
          # 4. Pay
          print('\nStep 3: Processing...')
          payment = monei.bills_pay.buy_electricity(
              biller_id=biller_id,
              customer_id=customer_id,
              amount=amount,
              type='PREPAID'
          )
          
          print(f'\n✓ Successful!')
          print(f'Reference: {payment.reference}')
          print(f'Total: ₦{payment.total_amount}')
          
          return payment
          
      except Exception as error:
          print(f'Failed: {error}')
          raise

  # Usage
  await complete_bill_payment('mtn-ng', '08012345678', 1000)
  ```
</CodeGroup>

***

## Payment by Category

<Tabs>
  <Tab title="Airtime">
    ```javascript theme={null}
    // Buy MTN airtime
    const payment = await monei.billsPay.buyAirtime({
      billerId: 'mtn-ng',
      customerId: '08012345678',
      amount: 1000,
      type: 'PREPAID'
    });
    ```

    **Processing:** Instant (\< 10 seconds)
    **Fee:** Free
    **Min:** ₦50, **Max:** ₦50,000
  </Tab>

  <Tab title="Data">
    ```javascript theme={null}
    // Buy MTN data bundle
    const payment = await monei.billsPay.buyMobileData({
      billerId: 'mtn-data-ng',
      customerId: '08012345678',
      amount: 1000,
      type: 'PREPAID',
      packageCode: 'MTN-1GB-MONTHLY'
    });
    ```

    **Processing:** Instant (\< 30 seconds)
    **Fee:** Free
    **Bundles:** Varies by network
  </Tab>

  <Tab title="Cable TV">
    ```javascript theme={null}
    // Renew DStv subscription
    const payment = await monei.billsPay.subscribeCableTv({
      billerId: 'dstv-ng',
      customerId: '1234567890',
      amount: 10500,
      type: 'PREPAID',
      packageCode: 'dstv-compact'
    });
    ```

    **Processing:** 1-5 minutes
    **Fee:** ₦50-₦100
    **Plans:** Multiple packages
  </Tab>

  <Tab title="Electricity">
    ```javascript theme={null}
    // Buy IKEDC prepaid units
    const payment = await monei.billsPay.buyElectricity({
      billerId: 'ikedc-prepaid',
      customerId: '12345678901',
      amount: 5000,
      type: 'PREPAID'
    });
    ```

    **Processing:** 1-10 minutes
    **Fee:** Free
    **Min:** ₦1,000, **Max:** ₦500,000
    **Token:** Returned in response
  </Tab>
</Tabs>

***

## Payment Status

Monitor payment progress:

| Status       | Description       | Action              |
| ------------ | ----------------- | ------------------- |
| `pending`    | Payment initiated | Wait for processing |
| `processing` | Being processed   | Wait for completion |
| `successful` | Payment completed | Service delivered   |
| `failed`     | Payment failed    | Check error, retry  |
| `reversed`   | Payment reversed  | Amount refunded     |

<CodeGroup>
  ```javascript Node.js theme={null}
  // Check payment status
  const status = await monei.billsRecord.getBillByReference('BILL-ABC123XYZ');

  console.log('Payment Status:', status.status);

  if (status.status === 'successful') {
    console.log('✓ Payment completed');
    if (status.token) {
      console.log('Electricity Token:', status.token);
    }
  } else if (status.status === 'failed') {
    console.log('✗ Payment failed');
    console.log('Reason:', status.failureReason);
  } else {
    console.log('⏳ Still processing...');
  }
  ```

  ```python Python theme={null}
  # Check status
  status = monei.bills_Record.get_bill_by_reference('BILL-ABC123XYZ')

  print(f'Status: {status.status}')

  if status.status == 'successful':
      print('✓ Completed')
      if status.token:
          print(f'Token: {status.token}')
  elif status.status == 'failed':
      print('✗ Failed')
      print(f'Reason: {status.failure_reason}')
  else:
      print('⏳ Processing...')
  ```
</CodeGroup>

***

## Electricity Token

For electricity payments, token is returned in the response:

<CodeGroup>
  ```javascript Node.js theme={null}
  // Buy electricity
  const payment = await monei.billsPay.buyElectricity({
    billerId: 'ikedc-prepaid',
    customerId: '12345678901',
    amount: 5000,
    type: 'PREPAID'
  });

  if (payment.status === 'successful' && payment.token) {
    console.log('✓ Payment successful!');
    console.log('\nElectricity Token:');
    console.log('Token:', payment.token);
    console.log('Units:', payment.units, 'kWh');
    console.log('Meter Number:', payment.customerId);
    console.log('Customer:', payment.customerName);
    console.log('Address:', payment.address);
    
    // Display to user or send via SMS/email
    sendTokenToCustomer(payment.token, payment.customerId);
  }
  ```

  ```python Python theme={null}
  # Buy electricity
  payment = monei.bills_pay.buy_electricity(
      biller_id='ikedc-prepaid',
      customer_id='12345678901',
      amount=5000,
      type='PREPAID'
  )

  if payment.status == 'successful' and payment.token:
      print('✓ Successful!\n')
      print('Electricity Token:')
      print(f'Token: {payment.token}')
      print(f'Units: {payment.units} kWh')
      print(f'Meter: {payment.customer_id}')
      print(f'Customer: {payment.customer_name}')
      
      # Send to customer
      send_token_to_customer(payment.token)
  ```
</CodeGroup>

***

## Error Handling

<AccordionGroup>
  <Accordion icon="wallet" title="Insufficient Balance">
    **Error:** Wallet balance too low

    **Solution:**

    ```javascript theme={null}
    // Check balance before payment
    const wallet = await monei.account.me();
    const balance = parseFloat(wallet.nairaBalance);
    const totalCost = amount + fee;

    if (balance < totalCost) {
      console.log('Insufficient balance');
      console.log('Need:', totalCost);
      console.log('Have:', balance);
      console.log('Shortage:', totalCost - balance);
      
      // Prompt user to fund wallet
      return;
    }
    ```
  </Accordion>

  <Accordion icon="circle-xmark" title="Payment Failed">
    **Error:** Payment processing failed

    **Common causes:**

    * Biller system down
    * Network issues
    * Invalid customer ID
    * Service unavailable

    **Solution:**

    * Check payment status
    * Amount automatically refunded
    * Retry after few minutes
    * Contact support if persists
  </Accordion>

  <Accordion icon="exclamation-triangle" title="Duplicate Payment">
    **Error:** Payment already processed

    **Cause:** Same reference used twice

    **Prevention:**

    ```javascript theme={null}
    // Generate unique reference
    const reference = `BILL-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;

    const payment = await monei.billsPay.buyAirtime({
      billerId: 'mtn-ng',
      customerId: '08012345678',
      amount: 1000,
      type: 'PREPAID',
      reference: reference
    });
    ```
  </Accordion>

  <Accordion icon="ban" title="Service Unavailable">
    **Error:** Biller service temporarily down

    **Action:**

    * Retry after 5-10 minutes
    * Try during off-peak hours
    * Use alternative biller if available
    * Check system status
  </Accordion>
</AccordionGroup>

***

## Best Practices

<CardGroup cols={2}>
  <Card title="Validate First" icon="check">
    Always validate customer before payment
  </Card>

  <Card title="Check Balance" icon="wallet">
    Verify sufficient funds before initiating
  </Card>

  <Card title="Save Reference" icon="bookmark">
    Keep payment reference for tracking
  </Card>

  <Card title="Show Confirmation" icon="circle-check">
    Display success message with details
  </Card>

  <Card title="Handle Errors" icon="bug">
    Implement proper error handling
  </Card>

  <Card title="Track Status" icon="eye">
    Monitor payment until successful
  </Card>
</CardGroup>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Overview" icon="circle-info" href="/bill-payments/overview">
    Bill payments introduction
  </Card>

  <Card title="Discovery" icon="magnifying-glass" href="/bill-payments/discovery">
    Browse available billers
  </Card>

  <Card title="Validation" icon="check" href="/bill-payments/validation">
    Validate customer details
  </Card>

  <Card title="History" icon="clock-rotate-left" href="/bill-payments/history">
    View payment history
  </Card>
</CardGroup>
