# API User Recharge and Bill Payment API Guide

This document explains how an API user can authenticate, check balance, get operator codes, send a mobile recharge request, fetch and pay bills, and check transaction status.

## Base URL

Use this production base URL:

```text
https://react.ayope.com/api/v1
```

## Authentication

Every API request must include these headers:

```text
X-API-KEY: your_api_key
X-TIMESTAMP: unix_timestamp
X-SIGNATURE: hmac_sha256_signature
Content-Type: application/json
Accept: application/json
```

The signature is generated using your API secret.

For `POST` requests:

```text
signature = HMAC_SHA256(timestamp + raw_json_body, api_secret)
```

For `GET` requests:

```text
signature = HMAC_SHA256(timestamp, api_secret)
```

The timestamp must be within the allowed server window, normally 300 seconds.

For simple GET integrations, mobile recharge, bill fetch, bill pay, and disputes can also authenticate through query parameters instead of headers:

```text
client_id=your_api_key
secret_key=your_api_secret
```

For the transaction status API, use `api_key` for your API account and `client_id` for your transaction/order ID.

## Signature Example

### PHP

```php
$apiKey = 'YOUR_API_KEY';
$apiSecret = 'YOUR_API_SECRET';
$timestamp = (string) time();

$payload = [
    'client_ref_id' => 'ORDER10001',
    'mobile' => '9876543210',
    'operator_code' => '1',
    'circle_code' => 'OD',
    'amount' => 199,
];

$body = json_encode($payload);
$signature = hash_hmac('sha256', $timestamp.$body, $apiSecret);
```

### Node.js

```js
const crypto = require('crypto');

const apiSecret = 'YOUR_API_SECRET';
const timestamp = Math.floor(Date.now() / 1000).toString();
const payload = {
  client_ref_id: 'ORDER10001',
  mobile: '9876543210',
  operator_code: '1',
  circle_code: 'OD',
  amount: 199
};

const body = JSON.stringify(payload);
const signature = crypto
  .createHmac('sha256', apiSecret)
  .update(timestamp + body)
  .digest('hex');
```

## Check Wallet Balance

```http
GET /api/v1/balance
```

### Success Response

```json
{
  "status": true,
  "balance": 10000,
  "locked_balance": 0,
  "currency": "INR"
}
```

## Get Operators

Use this API to get valid operator codes before sending recharge.

```http
GET /api/v1/operators?service_code=MOBILE_PREPAID
```

### Success Response

```json
{
  "status": true,
  "operators": [
    {
      "service_code": "MOBILE_PREPAID",
      "service_name": "Mobile Prepaid",
      "operator_code": "1",
      "operator_name": "Airtel",
      "min_amount": 10,
      "max_amount": 5000,
      "required_parameters": ["mobile", "circle_code"]
    }
  ]
}
```

## Send Mobile Recharge

```http
POST /api/v1/recharge/mobile
```

### Request Body

```json
{
  "client_ref_id": "ORDER10001",
  "mobile": "9876543210",
  "operator_code": "1",
  "circle_code": "OD",
  "amount": 199,
  "plan_code": "OPTIONAL_PLAN_CODE",
  "parameters": {}
}
```

### Request Fields

| Field | Required | Description |
| --- | --- | --- |
| `client_ref_id` | Yes | Unique reference ID from API user system. Duplicate values are rejected. |
| `mobile` | Yes | Customer mobile number, 10 to 15 digits. |
| `operator_code` | Yes | Operator code from operators API, for example `1`. Always confirm the current code from the operators API. |
| `circle_code` | Optional | Circle/state code if required by operator. |
| `amount` | Yes | Recharge amount. Minimum `1`. |
| `plan_code` | Optional | Plan identifier if your integration uses plan codes. |
| `parameters` | Optional | Extra provider-specific values. |

### Success Response

HTTP status: `202 Accepted`

```json
{
  "status": true,
  "transaction_id": "TXN20260504123000ABC123",
  "client_ref_id": "ORDER10001",
  "provider_ref_id": "DPR1234567890",
  "recharge_status": "pending",
  "transaction_status": "pending",
  "amount": 199,
  "commission": 0,
  "margin": 0,
  "surcharge": 0,
  "net_debit": 199,
  "idempotent_replay": false,
  "message": "Recharge request accepted"
}
```

`recharge_status` can be:

```text
initiated
wallet_debited
sent_to_provider
pending
success
failed
refunded
```

## Bill Payment - Step 1: Fetch Bill

Fetch the bill first to receive the `bill_fetch_id`, customer name, bill amount, and due date. Use that `bill_fetch_id` in the pay bill API.

### Endpoints

```http
POST /api/v1/bills/fetch
GET /api/v1/bills/fetch?client_id={your_api_key}&secret_key={your_api_secret}&client_ref_id=BILLFETCH10001&service_code=ELECTRICITY&biller_code=TATAPWR00DEL01&consumer_number=1234567892&customer_mobile=9876543210
```

### POST Request Body

```json
{
  "client_ref_id": "BILLFETCH10001",
  "service_code": "ELECTRICITY",
  "biller_code": "TATAPWR00DEL01",
  "consumer_number": "1234567892",
  "customer_mobile": "9876543210",
  "parameters": {
    "option1": "Ahmedabad",
    "option2": ""
  }
}
```

### Request Fields

| Field | Required | Description |
| --- | --- | --- |
| `client_ref_id` | Yes | Unique bill fetch reference ID from your system. |
| `service_code` | Yes | Service category, for example `ELECTRICITY`, `WATER`, `GAS`, or `FASTAG`. |
| `biller_code` | Yes | Biller/operator code from the operators API. |
| `consumer_number` | Yes | Consumer/account number for the biller. |
| `circle_code` | Optional | Circle/state code if required by the biller. |
| `customer_mobile` | Optional | Customer mobile number, 10 to 15 digits. Required by some billers. |
| `option1` | Optional | Additional biller value for providers that require it. |
| `option2` | Optional | Additional biller value for providers that require it. |
| `parameters` | Optional | JSON object with extra biller-specific values. |

### Success Response

HTTP status: `200 OK`

```json
{
  "status": true,
  "bill_fetch_id": "BF20260504123000ABC123",
  "customer_name": "Demo Customer",
  "bill_amount": 897,
  "due_date": "2026-05-31",
  "bill_number": "BF20260504123000ABC123",
  "idempotent_replay": false
}
```

### GET cURL Example

```bash
curl -G "https://react.ayope.com/api/v1/bills/fetch" \
  --data-urlencode "client_id=YOUR_API_KEY" \
  --data-urlencode "secret_key=YOUR_API_SECRET" \
  --data-urlencode "client_ref_id=BILLFETCH10001" \
  --data-urlencode "service_code=ELECTRICITY" \
  --data-urlencode "biller_code=TATAPWR00DEL01" \
  --data-urlencode "consumer_number=1234567892" \
  --data-urlencode "customer_mobile=9876543210"
```

## Bill Payment - Step 2: Pay Bill

Use this same API for both fetch-and-pay billers and direct/no-fetch billers.

- For fetch-required billers, pay the bill using the `bill_fetch_id` returned by the fetch bill API.
- For direct/no-fetch billers, send `bill_fetch_id` blank or omit it, and send `biller_code`, `consumer_number`, and `amount`. `service_code` is optional when the biller code identifies the operator.

### Endpoints

```http
POST /api/v1/bills/pay
GET /api/v1/bills/pay?client_id={your_api_key}&secret_key={your_api_secret}&client_ref_id=BILLPAY10001&bill_fetch_id={bill_fetch_id}&amount=897
GET /api/v1/bills/pay?client_id={your_api_key}&secret_key={your_api_secret}&client_ref_id=DIRECTPAY10001&bill_fetch_id=&biller_code=ASSA00000ASMOX&consumer_number=015000021660&amount=100
```

### POST Request Body - Fetch-Required Biller

```json
{
  "client_ref_id": "BILLPAY10001",
  "bill_fetch_id": "BF20260504123000ABC123",
  "amount": 897
}
```

### POST Request Body - Direct / No-Fetch Biller

```json
{
  "client_ref_id": "DIRECTPAY10001",
  "bill_fetch_id": "",
  "biller_code": "ASSA00000ASMOX",
  "consumer_number": "015000021660",
  "amount": 100
}
```

### Request Fields

| Field | Required | Description |
| --- | --- | --- |
| `client_ref_id` | Yes | Unique payment reference ID from your system. Use a different value from the fetch request. |
| `bill_fetch_id` | Conditional | Required for fetch-and-pay billers. For direct/no-fetch billers, omit it or send it blank. |
| `service_code` | Optional for direct/no-fetch | Service category, for example `ELECTRICITY`. If omitted, the API resolves the service from `biller_code`. |
| `biller_code` | Required for direct/no-fetch | Biller/operator code from the operators API. |
| `consumer_number` | Required for direct/no-fetch | Consumer/account number for the direct biller. |
| `circle_code` | Optional | Circle/state code if required by the biller. |
| `parameters` | Optional | Extra biller-specific values. |
| `amount` | Yes | Payment amount. For fetch-required exact billers, this must match `bill_amount`. |

### Success Response

HTTP status: `202 Accepted`

```json
{
  "status": true,
  "transaction_id": "TXN20260504123500ABC123",
  "client_ref_id": "BILLPAY10001",
  "operator_txn_id": null,
  "transaction_status": "pending",
  "payment_status": "pending",
  "amount": 1250,
  "commission": 0,
  "margin": 0,
  "surcharge": 0,
  "net_debit": 1250,
  "idempotent_replay": false,
  "message": "Bill payment request accepted"
}
```

### GET cURL Example

Fetch-required biller:

```bash
curl -G "https://react.ayope.com/api/v1/bills/pay" \
  --data-urlencode "client_id=YOUR_API_KEY" \
  --data-urlencode "secret_key=YOUR_API_SECRET" \
  --data-urlencode "client_ref_id=BILLPAY10001" \
  --data-urlencode "bill_fetch_id=BF20260504123000ABC123" \
  --data-urlencode "amount=897"
```

Direct/no-fetch biller:

```bash
curl -G "https://react.ayope.com/api/v1/bills/pay" \
  --data-urlencode "client_id=YOUR_API_KEY" \
  --data-urlencode "secret_key=YOUR_API_SECRET" \
  --data-urlencode "client_ref_id=DIRECTPAY10001" \
  --data-urlencode "bill_fetch_id=" \
  --data-urlencode "biller_code=ASSA00000ASMOX" \
  --data-urlencode "consumer_number=015000021660" \
  --data-urlencode "amount=100"
```

## Mobile Recharge cURL Example

Generate the signature in your application first, then send:

```bash
curl -X POST "https://react.ayope.com/api/v1/recharge/mobile" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "X-API-KEY: YOUR_API_KEY" \
  -H "X-TIMESTAMP: 1777900000" \
  -H "X-SIGNATURE: GENERATED_SIGNATURE" \
  -d '{
    "client_ref_id": "ORDER10001",
    "mobile": "9876543210",
    "operator_code": "1",
    "circle_code": "OD",
    "amount": 199
  }'
```

## Check Transaction Status

Use `client_id` in the query string to check status. This value is your transaction/order ID from your system, the same value sent as `client_ref_id` during recharge or bill payment.

Important:

- The `client_id` query value selects the transaction, for example `client_id=ORDER10001`.
- Do not pass B2B Ayope's `transaction_id` in the status URL.
- For this Status API, `client_id` means your transaction/order ID.
- For no-header GET authentication, send `api_key` and `secret_key` with the same URL.

For simple GET integrations, authentication may be sent as query parameters:

```http
GET /api/v1/transactions/status?api_key={your_api_key}&client_id={your_transaction_id}&secret_key={your_secret_key}
```

Example:

```http
GET /api/v1/transactions/status?api_key=YOUR_API_KEY&client_id=ORDER10001&secret_key=YOUR_SECRET_KEY
```

In this example:

| Value | Meaning |
| --- | --- |
| `api_key=YOUR_API_KEY` | Your API key; this identifies your API account. |
| `client_id=ORDER10001` | Your transaction/order ID; this selects the transaction. |
| `secret_key` | Your API secret; this authenticates the request. |

### Success Status Response

```json
{
  "status": true,
  "transaction_id": "TXN20260504123000ABC123",
  "client_ref_id": "ORDER10001",
  "transaction_status": "success",
  "operator_txn_id": "OP123456",
  "operator_ref_id": "OP123456",
  "amount": 199,
  "commission": 0,
  "margin": 0,
  "surcharge": 0,
  "net_debit": 199,
  "message": "Transaction status fetched successfully"
}
```

### Failed Status Response

```json
{
  "status": true,
  "transaction_id": "TXN20260504123000ABC123",
  "client_ref_id": "ORDER10001",
  "transaction_status": "failed",
  "operator_txn_id": null,
  "operator_ref_id": null,
  "amount": 199,
  "commission": 0,
  "margin": 0,
  "surcharge": 0,
  "net_debit": 199,
  "message": "Provider rejected the transaction"
}
```

### Pending Status Response

```json
{
  "status": true,
  "transaction_id": "TXN20260504123000ABC123",
  "client_ref_id": "ORDER10001",
  "transaction_status": "pending",
  "operator_txn_id": null,
  "operator_ref_id": null,
  "amount": 199,
  "commission": 0,
  "margin": 0,
  "surcharge": 0,
  "net_debit": 199,
  "message": "Transaction status fetched successfully"
}
```

### Transaction Not Found

HTTP status: `404 Not Found`

```json
{
  "status": false,
  "error_code": "TRANSACTION_NOT_FOUND",
  "message": "Transaction was not found."
}
```

## Error Responses

### Authentication Failed

HTTP status: `401`

```json
{
  "status": false,
  "error_code": "AUTH_FAILED",
  "message": "Invalid API credentials."
}
```

### Invalid Signature

HTTP status: `401`

```json
{
  "status": false,
  "error_code": "INVALID_SIGNATURE",
  "message": "Invalid API signature."
}
```

### Duplicate Reference

HTTP status: `422`

```json
{
  "status": false,
  "error_code": "DUPLICATE_REFERENCE",
  "message": "Duplicate client reference ID."
}
```

### Insufficient Balance

HTTP status: `422`

```json
{
  "status": false,
  "error_code": "INSUFFICIENT_BALANCE",
  "message": "Insufficient wallet balance."
}
```

## Important Notes

- Always send a unique `client_ref_id` for every recharge, bill fetch, and bill payment.
- Store `transaction_id` and `client_ref_id` in your system.
- Use status check API for final status if recharge or bill payment response is `pending`.
- Do not reuse the same `client_ref_id` with different request details.
- For direct/no-fetch billers, a blank `bill_fetch_id` is accepted. The parameter name must still be exactly `bill_fetch_id`.
- If IP whitelist is enabled for your API key, requests must come from an allowed IP.
