---
title: "Pay BBPS Bill API Reference"
description: "Process a bill payment or recharge for any BBPS-connected biller."
canonical: "https://eps.eko.in/docs/bbps-pay-bill"
---


> **Canonical URL:** https://eps.eko.in/docs/bbps-pay-bill
> This is a machine-readable Markdown version of the page for AI agents and LLMs. The primary (HTML) version lives at the canonical URL above.

# Pay BBPS Bill API Reference

`POST https://staging.eko.in/ekoapi/v3/customer/payment/bbps`

Process a bill payment or recharge for any BBPS-connected biller.

**Behaviour**

- **Moves money**: Moves real money and cannot be undone. After a timeout, confirm the outcome before ever re-sending.
- **[Earns commission](https://eps.eko.in/pricing?tab=payments#payments-calculator)**: You earn a commission per bill, by biller category, amount and settlement mode.

The money-debit call that pays a bill or submits a recharge on the BBPS network. For a bill payment, send the `amount` confirmed at Fetch Bill and the `utilitycustomername` it returned. A prepaid recharge skips Fetch Bill, so it sends the chosen plan's amount and omits `utilitycustomername`.

**Pay the exact amount returned by Fetch Bill** — a mismatch is rejected with status `208`. On `208`, re-fetch the bill and retry with a **fresh** `client_ref_id`; a `client_ref_id` identifies one payment attempt and must never be reused across retries. Persist `tid` and your `client_ref_id` before any retry — status `208` still returns a `tid`.

**Parameters vary by operator.** The fields below are the common set; pass every `param_name` returned by Get Operator Parameters as well. The parameter set sent here must match the set sent to Fetch Bill for the same operator.

> View product & pricing details: [Bharat Bill Payment System (BBPS)](https://eps.eko.in/products/bbps-api.md)

## Body parameters

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| initiator_id | string | yes | Registered mobile number of the API user (see Platform Credentials). e.g. 9962981729 |
| phone_operator_code | string | yes | Biller identifier — the `operator_id` from the Get Operators response. e.g. 53 |
| utility_acc_no | string | yes | Bill/account number. For a prepaid recharge, the customer's mobile number. e.g. 3287820071 |
| confirmation_mobile_no | string | yes | Customer's alternate mobile number. This is only used for sending the confirmation SMS. It may be same as the `utility_acc_no` for prepaid recharges. e.g. 9903457748 |
| sender_name | string | yes | Customer name. e.g. Asaad |
| category | number | yes | The `operator_category_id` from Get Categories (e.g. `8` = Electricity). e.g. 8 |
| amount | number | yes | Amount to pay, in rupees. Must equal the `amount` returned by Fetch Bill. e.g. 2870 |
| utilitycustomername | string | no | Customer name as returned by Fetch Bill. Mandatory for bill payments where Bill Fetch is done. Not applicable to prepaid recharges, which skip Bill Fetch. e.g. Amit Kumar |
| client_ref_id | string | yes | Unique partner reference for this payment attempt. Reuse the value sent to the matching Fetch Bill call; generate a fresh one for every retry. e.g. 2026010100123456789 |
| source_ip | string | yes | Originating client IP address. e.g. 192.168.1.1 |
| district_discome | string | no | District-level distribution company code. Required for **operator 190 (UPPCL) only** — pass the same value used at Fetch Bill. e.g. Lucknow-MVVNL |
| communication | number | no | Payment mode: `0` (default) = online — instant settlement, lower commission. `1` = offline — higher commission, but the bill takes a minimum of 6 working hours to settle. Pass the same value used at Fetch Bill. e.g. 0 |

## Headers

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| developer_key | string | yes | Static API key issued to your account after KYC. |
| secret-key | string | yes | Dynamic per-request signature: base64(HMAC-SHA256(timestamp, base64(access_key))). |
| secret-key-timestamp | string | yes | Current time in milliseconds since UNIX epoch, used to compute secret-key. Must match server time. |
| content-type | string | yes | application/json e.g. application/json |

## Response

⭐ marks fields highlighted as verifiable.

| Field | Type | Description |
| --- | --- | --- |
| status | number | Primary success indicator (0 = success). |
| message | string | Human-readable response / error message. |
| response_status_id | number | UI display hint only (-1/0 success, 1 failure, 2 initiated, 3 refund initiated, 4 refunded). Never branch on it — use `status` (and `tx_status` for financial APIs), or `response_type_id` where documented. |
| response_type_id | number | A unique id for every possible response shape (success or error) — useful for client logic branching and analytics. |
| tx_status | string | Transaction state: 0=Success, 1=Fail, 2=Initiated / Response Awaited (NEFT) — poll Transaction Inquiry, 3=Refund Pending, 4=Refunded, 6=Response Awaited — Transaction Inquiry required. |
| txstatus_desc | string | Human-readable transaction status. |
| data | object | API-specific response payload. |
| data.tid ⭐ | string | Eko transaction ID. Store it for reconciliation and dispute resolution — returned on failures too. |
| data.tx_status ⭐ | string | Transaction status (`0` = success). |
| data.txstatus_desc | string | Human-readable transaction status. |
| data.status_text | string | Status label from the biller. |
| data.amount ⭐ | string | Amount paid. |
| data.totalamount | string | Total amount debited, including any fee. |
| data.fee | string | Fee charged for this transaction. |
| data.tds | string | TDS deducted on the commission. |
| data.commission | string | Agent commission earned on this payment. |
| data.balance ⭐ | string | Agent wallet balance after the payment. |
| data.operator_name | string | Biller the payment was made to. |
| data.utilitycustomername | string | Customer name on the bill. |
| data.customermobilenumber | string | Customer mobile number. |
| data.account | string | Account / consumer number that was paid. |
| data.approvalreferencenumber | string | Biller approval reference, where provided. |
| data.payment_mode_desc | string | Payment mode used. |
| data.user_code | string | Agent's user code. |
| data.last_used_okekey | string | Last used OkeKey. |
| data.timestamp | string | Transaction timestamp. |

## Response types

Branch on `response_type_id` to decide the next call:

| response_type_id | Meaning | Next step |
| --- | --- | --- |
| 333 | Payment successful — persist `tid` and `client_ref_id` for reconciliation. | — |
| 208 | Amount does not match the bill. Re-fetch the bill and retry with a fresh `client_ref_id`; a `tid` is still returned, so persist it first. | [bbps-fetch-bill](https://eps.eko.in/docs/bbps-fetch-bill.md) |

## Example request

```json
{
  "initiator_id": "9962981729",
  "phone_operator_code": "53",
  "utility_acc_no": "3287820071",
  "confirmation_mobile_no": "9903457748",
  "sender_name": "Asaad",
  "category": 8,
  "amount": 2870,
  "utilitycustomername": "Amit Kumar",
  "client_ref_id": "2026010100123456789",
  "source_ip": "192.168.1.1",
  "district_discome": "Lucknow-MVVNL",
  "communication": 0
}
```

## Example response

`response_type_id` `333` — Payment successful — persist `tid` and `client_ref_id` for reconciliation..

```json
{
  "response_status_id": 0,
  "data": {
    "tx_status": "0",
    "txstatus_desc": "Success",
    "status_text": "SUCCESS",
    "tid": "3570553488",
    "amount": "2870.0",
    "totalamount": "2870.0",
    "fee": "0.0",
    "tds": "0.024",
    "commission": "1.2",
    "balance": "46537.3",
    "user_code": "35739001",
    "operator_name": "B.E.S.T Mumbai",
    "utilitycustomername": "Amit Kumar",
    "customermobilenumber": "9903457748",
    "payment_mode_desc": "CASH",
    "last_used_okekey": "203",
    "account": "3287820071",
    "timestamp": "2026-07-25T09:52:57.428Z"
  },
  "response_type_id": 333,
  "message": "Success Last_used_OkeyKey: 203",
  "status": 0
}
```

## Error scenarios

| Status | response_type_id | Scenario |
| --- | --- | --- |
| 200 | `208` — Amount does not match the bill. Re-fetch the bill and retry with a fresh `client_ref_id`; a `tid` is still returned, so persist it first. | Amount mismatch — the amount paid differs from the fetched bill |
| 200 | `-1` | Required field missing |
