> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.senjaropay.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.senjaropay.com/_mcp/server.

# Bill payments

Pay electricity, government control numbers, TV subscriptions, and other bills from your SenjaroPay merchant wallet.

Browse categories, confirm the customer account with a lookup, then settle the bill. All endpoints are **POST** to `https://api.senjaropay.com` and require **`x-api-key`** and **`x-api-secret`**.

## How it works

#### List categories

Call categories to show the bill groups in your UI (utilities, government, TV, and more).

#### List billers

Pass a `category_id` to load the billers in that group. Each biller returns a `utilityCode` and the reference field your customer should enter.

#### Look up the account

When `lookupAvailable` is `true`, validate the meter, control number, or account before charging. Show the returned customer name for confirmation.

#### Pay

Send `utility`, `utility_ref`, and `amount`. Store `data.transid` from the response.

#### Check status

If the pay result is unclear, or you need to reconcile later, query status with `transid`.

## Authentication

| Header         | Required | Description                                                  |
| -------------- | -------- | ------------------------------------------------------------ |
| `Content-Type` | Yes      | `application/json`                                           |
| `x-api-key`    | Yes      | Dashboard **Public Key** ([Authentication](/authentication)) |
| `x-api-secret` | Yes      | Secret key. Server-side only.                                |

```http
POST /api/billPayments/categories HTTP/1.1
Host: api.senjaropay.com
Content-Type: application/json
x-api-key: <public_key>
x-api-secret: <secret>
```

## 1. List categories

```
POST https://api.senjaropay.com/api/billPayments/categories
```

No request body.

### Response

```json
{
  "status": "success",
  "code": 200,
  "data": [
    {
      "id": 4,
      "name": "Government Payments",
      "icon": "Landmark"
    },
    {
      "id": 1,
      "name": "Utility Services",
      "icon": "Lightbulb"
    },
    {
      "id": 5,
      "name": "Travel & Ticket Booking",
      "icon": "Plane"
    },
    {
      "id": 3,
      "name": "Prepaid Internet",
      "icon": "Globe"
    },
    {
      "id": 2,
      "name": "TV Subscriptions",
      "icon": "Monitor"
    },
    {
      "id": 6,
      "name": "Investment & Pension Funds",
      "icon": "LineChart"
    }
  ]
}
```

| Field  | Description                                      |
| ------ | ------------------------------------------------ |
| `id`   | Pass as `category_id` when listing subcategories |
| `name` | Display name for the category                    |
| `icon` | Icon key for your client UI                      |

```bash
curl -sS -X POST "https://api.senjaropay.com/api/billPayments/categories" \
  -H "Content-Type: application/json" \
  -H "x-api-key: ${SENJARO_API_KEY}" \
  -H "x-api-secret: ${SENJARO_API_SECRET}" \
  -d '{}'
```

## 2. List subcategories

```
POST https://api.senjaropay.com/api/billPayments/subcategories
```

### Request

```json
{
  "category_id": "4"
}
```

| Field         | Type   | Required | Description                       |
| ------------- | ------ | -------- | --------------------------------- |
| `category_id` | string | Yes      | `id` from the categories response |

### Response

`data` is keyed by category name. Each entry is a biller you can look up and pay.

```json
{
  "status": "success",
  "code": 200,
  "data": {
    "Government Payments": [
      {
        "id": 11,
        "utilityCode": "GEPG",
        "refLabel": "Control No",
        "refType": "Numeric(12)",
        "refExample": "991234567891",
        "lookupAvailable": true,
        "description": "Government bill payment across supported agencies",
        "logo": "https://cdn.example.com/bills/gepg.png"
      }
    ]
  }
}
```

| Field             | Description                            |
| ----------------- | -------------------------------------- |
| `utilityCode`     | Pass as `utility` on lookup and pay    |
| `refLabel`        | Label for the customer reference input |
| `refType`         | Expected reference format              |
| `refExample`      | Sample value for your UI               |
| `lookupAvailable` | When `true`, call lookup before pay    |

```bash
curl -sS -X POST "https://api.senjaropay.com/api/billPayments/subcategories" \
  -H "Content-Type: application/json" \
  -H "x-api-key: ${SENJARO_API_KEY}" \
  -H "x-api-secret: ${SENJARO_API_SECRET}" \
  -d '{"category_id":"4"}'
```

## 3. Look up an account

```
POST https://api.senjaropay.com/api/billPayments/lookup
```

Use this when the biller has `lookupAvailable: true`. Confirm the returned customer name with your payer before charging.

### Request

```json
{
  "utility": "LUKU",
  "utility_ref": "43036017606"
}
```

| Field         | Type   | Required | Description                                 |
| ------------- | ------ | -------- | ------------------------------------------- |
| `utility`     | string | Yes      | `utilityCode` from the subcategory          |
| `utility_ref` | string | Yes      | Meter number, control number, or account ID |

### Response

```json
{
  "status": "success",
  "code": 200,
  "data": {
    "lookup_transid": "LOOKUP_MOCK_7f3a91c2",
    "transaction_id": "70effccb-2b9e-4b3f-8b47-c7fa873f1af3",
    "utility": "LUKU",
    "utility_ref": "43036017606",
    "result": "SUCCESS",
    "resultcode": "000",
    "message": "LUKU Confirmation\nTest Customer\nMeter# 43036017606\n",
    "lookup": [
      {
        "name": "Test Customer"
      }
    ]
  }
}
```

| Field                   | Description                                                  |
| ----------------------- | ------------------------------------------------------------ |
| `result` / `resultcode` | Lookup outcome. `SUCCESS` / `000` means the account is valid |
| `lookup`                | Customer details to show before payment                      |
| `message`               | Provider confirmation text                                   |

```bash
curl -sS -X POST "https://api.senjaropay.com/api/billPayments/lookup" \
  -H "Content-Type: application/json" \
  -H "x-api-key: ${SENJARO_API_KEY}" \
  -H "x-api-secret: ${SENJARO_API_SECRET}" \
  -d '{"utility":"LUKU","utility_ref":"43036017606"}'
```

## 4. Pay a bill

```
POST https://api.senjaropay.com/api/billPayments/pay
```

Settles the bill from your merchant wallet. Store `data.transid` for status checks.

### Request

```json
{
  "utility": "LUKU",
  "utility_ref": "54205084277",
  "amount": 2000,
  "phone": "255700000001"
}
```

| Field         | Type    | Required | Description                                                                                               |
| ------------- | ------- | -------- | --------------------------------------------------------------------------------------------------------- |
| `utility`     | string  | Yes      | `utilityCode` from the subcategory                                                                        |
| `utility_ref` | string  | Yes      | Same reference used at lookup                                                                             |
| `amount`      | integer | Yes      | Amount in TZS                                                                                             |
| `phone`       | string  | No       | Payer MSISDN for the confirmation SMS. If omitted, SenjaroPay sends the SMS to the merchant phone on file |

### Response

```json
{
  "status": "success",
  "code": 200,
  "data": {
    "transaction_id": "eef01eba-d42b-4ea3-9581-7778c75123aa",
    "transid": "2dd9486c-bb19-4556-bade-482bf97a2b06",
    "reference": "1949333867",
    "utility": "LUKU",
    "utility_ref": "54205084277",
    "amount": 2000,
    "currency": "TZS",
    "result": "SUCCESS",
    "resultcode": "000",
    "message": "LUKU\nTest Customer\nMeter 54205084277\nUnits 5.6kWh\nToken 0105 6819 2412 0556 9485\nTOTAL TZS 2,000\nReference 1949333867"
  }
}
```

| Field                   | Description                                                  |
| ----------------------- | ------------------------------------------------------------ |
| `transid`               | Use this on the status endpoint                              |
| `reference`             | Provider payment reference                                   |
| `result` / `resultcode` | Payment outcome                                              |
| `message`               | Receipt text. Format varies by utility (tokens, units, fees) |

```bash
curl -sS -X POST "https://api.senjaropay.com/api/billPayments/pay" \
  -H "Content-Type: application/json" \
  -H "x-api-key: ${SENJARO_API_KEY}" \
  -H "x-api-secret: ${SENJARO_API_SECRET}" \
  -d '{
    "utility": "LUKU",
    "utility_ref": "54205084277",
    "amount": 2000,
    "phone": "255700000001"
  }'
```

## 5. Check status

```
POST https://api.senjaropay.com/api/billPayments/status
```

Use when the pay response is unclear, or to reconcile after a timeout.

### Request

```json
{
  "transid": "2dd9486c-bb19-4556-bade-482bf97a2b06"
}
```

| Field     | Type   | Required | Description                          |
| --------- | ------ | -------- | ------------------------------------ |
| `transid` | string | Yes      | `data.transid` from the pay response |

### Response

```json
{
  "status": "success",
  "code": 200,
  "data": {
    "transaction_id": "eef01eba-d42b-4ea3-9581-7778c75123aa",
    "transid": "2dd9486c-bb19-4556-bade-482bf97a2b06",
    "reference": "1949333867",
    "amount": "2000.00",
    "currency": "TZS",
    "payment_status": "SUCCESS",
    "result": "SUCCESS",
    "resultcode": "000",
    "message": "LUKU\nTest Customer\nMeter 54205084277\nUnits 5.6kWh\nToken 0105 6819 2412 0556 9485\nTOTAL TZS 2,000\nReference 1949333867"
  }
}
```

| Field                   | Description                           |
| ----------------------- | ------------------------------------- |
| `payment_status`        | Current bill payment state            |
| `result` / `resultcode` | Provider outcome codes                |
| `message`               | Latest receipt text from the provider |

```bash
curl -sS -X POST "https://api.senjaropay.com/api/billPayments/status" \
  -H "Content-Type: application/json" \
  -H "x-api-key: ${SENJARO_API_KEY}" \
  -H "x-api-secret: ${SENJARO_API_SECRET}" \
  -d '{"transid":"2dd9486c-bb19-4556-bade-482bf97a2b06"}'
```

## Errors

| HTTP status | Typical `error_code` | When                                                |
| ----------- | -------------------- | --------------------------------------------------- |
| **400**     | `validation_error`   | Missing field, invalid amount, or unknown `utility` |
| **401**     | `unauthorized`       | Missing or invalid `x-api-key` or `x-api-secret`    |

```json
{
  "status": "error",
  "code": 400,
  "error_code": "validation_error",
  "message": "utility_ref is required"
}
```

Examples on this page are mock values. Keep API keys in server-side secrets.