/

to search

Introducing Setu Changelog Check it out ↗

#When Users Need to Select Plans

#1. Overview

Some services require your users to choose a plan before payment - like mobile recharge plans, DTH packages, or broadband subscriptions. This guide shows you how to handle these plan selection flows in your app.

šŸ“– This extends Flow 2: Bill Validation → Payment from the master guide

What this means for your users:

  • Instead of paying a bill amount, they choose from available plans
  • Plans have fixed prices and specific benefits (data, validity, channels, etc.)
  • Payment happens after plan selection

#1.1 Common Services That Need Plans

  • Mobile Prepaid Recharge - Data plans, talk time, combo offers
  • DTH/Cable TV - Channel packages, validity periods
  • Broadband Services - Speed upgrades, data top-ups
  • OTT Subscriptions - Monthly, annual, family plans

#1.2 What You'll Build

  • Plan selection screens for your users
  • Integration with plan APIs
  • Validation and payment flows with selected plans

#2. Two User Experience Patterns

Your users will encounter one of two plan selection patterns, depending on the service:

#2.1 Pattern 1: Choose From Full Catalog

User Flow: Browse plans → Select plan → Enter account details → Pay

What users see: Complete list of available plans upfront (like mobile recharge plans)

Examples: BSNL/MTNL mobile recharge, DTH packages, OTT subscriptions

#2.2 Pattern 2: Get Personalized Options

User Flow: Enter account details → See custom plans → Select plan → Pay

What users see: Plans tailored to their account (like broadband upgrade options)

Examples: You Broadband plans, Airtel Wi-Fi recharge options


#3. Implementation Guide

#3.1 Pattern 1: Choose From Full Catalog

User Experience: Show all available plans immediately, let user choose, then collect account details.

Implementation Steps:

  1. Get Available Plans → GET /api/v2/bbps/billers/plans
  2. User Selects Plan + Enters Details → Your app collects both
  3. Validate Account + Plan → POST /api/v2/bbps/bills/fetch/request (include plan ID)
  4. Process Payment → POST /api/v2/bbps/bills/payment/request

šŸ’” Key Point: You must include the selected plan ID when validating the account to ensure the plan is still available.

#3.2 Pattern 2: Get Personalized Options

User Experience: Collect account details first, then show plans customized for that account.

Implementation Steps:

  1. User Enters Account Details → Your app collects account info
  2. Validate Account → POST /api/v2/bbps/bills/fetch/request (no plan ID)
  3. Get Custom Plans → Response includes plans available for this account
  4. User Selects Plan → Your app presents the options
  5. Process Payment → POST /api/v2/bbps/bills/payment/request (include plan ID)

šŸ’” Key Point: Plans are revealed only after account validation, so you can't show them upfront.

#3.3 Quick Reference: Which Pattern to Use

PatternWhen Plans Are ShownUser FlowCommon Examples
Pattern 1Immediately availableBrowse plans → Select → Enter details → PayMobile recharge, DTH packages
Pattern 2After account validationEnter details → See custom plans → Select → PayBroadband upgrades, account-specific offers

#3.4 How to Detect Which Pattern to Implement

Check the biller metadata from List Billers API to determine the pattern:

Pattern 1 Detection:

{
  "planRequirement": "MANDATORY"
}

Pattern 2 Detection:

{
  "planRequirement": "OPTIONAL",
  "responseType": "SELECTIVE"
}

Other billers require no plan selection.

→ Use standard Bill Validation flow


#4. Pattern 1: Full Catalog Selection

What this means: All available plans can be fetched upfront and shown to users immediately.

#4.1 Examples of This Pattern

ServiceWhat User EntersWhat User Selects From
BSNL/MTNL MobileMobile Number, CircleData plans, talk time, combo offers
Hungama PlayMobile Number, EmailMonthly, yearly subscription plans
Sun Direct TVSubscriber NumberChannel packages, validity periods

#4.2 Step 1: Get Available Plans

#4.2.1 Fetch All Plans for a Service

Retrieve all available plans for specific billers using the dedicated endpoint (See API Reference).

Request: GET /api/v2/bbps/billers/plans?billerIds=BILLER_ID

Response:

Sample Response
{
"data": {
"plans": [
{
"Id": "3",
"additionalInfo": [
{
"paramName": "Package Details",
"paramValue": "Family Package"
},
{
"paramName": "Channels",
"paramValue": "200+"
},
{
"paramName": "Devices",
"paramValue": "Up to 3"
}
],
"amountInRupees": "99",
"billerId": "ZEE500000NAT01",
"categorySubType": {
"subType": "Family"
},
"categoryType": "STANDARD",
"description": "Family Pack with 200+ channels",
"effectiveFrom": null,
"effectiveTo": null,
"status": "ACTIVE"
},
{
"Id": "2",
"additionalInfo": [
{
"paramName": "Package Details",
"paramValue": "Entertainment Package"
},
{
"paramName": "Channels",
"paramValue": "100+"
}
],
"amountInRupees": "49",
"billerId": "ZEE500000NAT01",
"categorySubType": {
"subType": "Entertainment"
},
"categoryType": "BASIC",
"description": "Entertainment Pack with 100+ channels",
"effectiveFrom": null,
"effectiveTo": null,
"status": "ACTIVE"
}
],
"total": 2
},
"success": true,
"traceId": "CVOHOVGATEUJ1SDODBKG"
}

#4.2.2 Pagination Support

For billers with large plan catalogs, the API supports efficient pagination:

Initial Request: GET /api/v2/bbps/billers/plans?billerIds=YOUR_BILLER_ID&limit=1000

Pagination Response Fields:

FieldDescription
data.plansArray containing current page plans
data.totalTotal number of plans matching query
data.nextPageURL for next page (null if last page)

Next Page Request: GET /api/v2/bbps/billers/plans?billerIds=YOUR_BILLER_ID&limit=100&after=LAST_PLAN_ID_FROM_PAGE_1

Pagination Example:

For a biller with 3,700 plans using limit=1000:

RequestResponseNext Page
GET …&limit=10001000 plansafter=PLAN_1000&limit=1000
GET …&after=PLAN_10001000 plansafter=PLAN_2000&limit=1000
GET …&after=PLAN_20001000 plansafter=PLAN_3000&limit=1000
GET …&after=PLAN_3000700 plansnull (complete)

#4.2.3 Plan Structure

Each plan object contains both mandatory and optional fields:

interface Plan {
// Mandatory fields
Id: string; // 1-32 chars, alphanumeric
categoryType: string; // 1-100 chars, alphanumeric
amountInRupees: string; // 1-10 digits, decimals supported
description: string; // text with special chars allowed
effectiveFrom: string; // ISO date format
effectiveTo: string; // ISO date format
status: "ACTIVE" | "DEACTIVATED";
// Optional fields
categorySubType?: {
subType: string;
};
additionalInfo?: Array<{
paramName: string;
paramValue: string;
}>;
}

#4.2.4 Plan Update Webhooks

Receive real-time notifications when biller plans are modified (See Webhook Reference):

Sample Webhook Payload
{
"event": "PLAN_UPDATES",
"timeStamp": "2025-04-08T12:34:29.603+05:30",
"data": {
"billerId": "ZEE500000NAT01",
"Id": "3",
"amountInRupees": "599.0",
"categoryType": "Premium",
"categorySubType": {
"subType": "6 Months"
},
"description": "All ZEE5 Originals and Exclusives, Blockbuster Movies, All ALT Balaji Shows, Zindagi TV Shows,
Kids, Live TV, TV shows before telecast. Watch on 5 devices at a time",
"effectiveFrom": "2021-01-01",
"effectiveTo": "2021-12-31",
"status": "ACTIVE"
}
}

#4.3 Step 2: Present Plans to Users

For Mobile Recharge: Use the first 4-5 digits of the mobile number to auto-detect operator and circle, but always let users change these values.

#4.4 Step 3: Validate Account + Selected Plan

Request Format: Most static plan billers accept the plan ID as customer.customerParams[name="Id"]. Include the plan ID from Step 1 along with the user's account details.

POST /api/v2/bbps/bills/fetch/request
{
"biller": { "id": "{{BILLER_ID}}" },
"customer": {
"mobile": "9999999999",
"customerParams": [
{ "name": "Id", "value": "3" },
{ "name": "Subscriber Number", "value": "ABC12345" }
]
},
"agent": { "id": "{{AGENT_ID}}", "channel": "INT" }
}

Note: If a biller uses a different parameter name for plan ID, check that biller's specification from List Billers API.

**V1 users:** Use

customer.billParameters
instead of
customer.customerParams
.

Complete Request Example:

Sample Request
{
"agent": {},
"customer": {
"mobile": "8484943411",
"customerParams": [
{
"name": "Mobile Number",
"value": "9987654321"
},
{
"name": "Circle",
"value": "Karnataka"
},
{
"name": "Id",
"value": "BSNL_PLAN_123"
}
]
},
"biller": {
"id": "BILLER_ID"
}
}

Response:

Sample Response
{
"data": {
"refId": "CSJ1BPJEA37IGH20GILGDfl3qOd43071737"
},
"success": true,
"traceId": "CSJ1BPJEA37IGH20GIL0"
}

#4.4.1 Check Validation Status

Request: POST /api/v2/bbps/bills/fetch/response

Sample Response
{
"refId": "CSJ1BPJEA37IGH20GILGDfl3qOd43071737"
}

Response:

Sample Response
{
"success": true,
"traceId": "CR3J63KR22BP6FC8N9B0",
"data": {
"additionalInfo": [],
"billerRefId": "ABCD1234",
"exactness": "Any",
"refId": "CSJ1BPJEA37IGH20GILGDfl3qOd43071737",
"status": "Success"
}
}

#4.4.2 Validation Webhook

Sample Validation Webhook Payload
{
"event": "BILL_VALIDATE",
"timeStamp": "2024-11-26T08:06:44.060+05:30",
"data": {
"additionalInfo": [],
"billerRefId": "836480286",
"exactness": "Any",
"refId": "CSJ1BPJEA37IGH20GILGDfl3qOd43071737",
"status": "Success"
}
}

#4.5 Step 4: Process Payment

Process payment for validated plans using the reference ID from validation.

Request: POST /api/v2/bbps/bills/payment/request

Sample Request
{
"refId": "CSJ1BPJEA37IGH20GILGDfl3qOd43071737",
"paymentDetails": {
"mode": "Debit Card",
"paymentRefId": "1zw2B959aLpxqv",
"amount": 2200,
"timestamp": "2024-11-18T19:12:05+05:30"
}
}

šŸ’° Amount Format: All amounts must be specified in paise (1 Rupee = 100 paise) and must match the selected plan's amount exactly.

Response:

Sample Response
{
"data": {
"refId": "CSJ1BPJEA37IGH20GILGDfl3qOd43071737"
},
"success": true,
"traceId": "CSJ1BRREA37IGH20GIO0"
}

#4.5.1 Check Payment Status

Request: POST /api/v2/bbps/bills/payment/response

Sample Request
{
"refId": "CSJ1BPJEA37IGH20GILGDfl3qOd43071737"
}

Response:

Sample Response
{
"success": true,
"traceId": "CSJ1BSREA37IGH20GIQ0",
"data": {
"additionalInfo": [],
"billerRefId": "8925477974299500719",
"paymentDetails": {
"amount": 2200,
"mode": "Debit Card",
"paymentRefId": "REZYOXmwbDF3bx",
"timestamp": "2024-11-02T17:37:11.000+05:30"
},
"refId": "CSJ1BPJEA37IGH20GILGDfl3qOd43071737",
"status": "Success",
"transactionId": "DP014307173711LO95Q9"
}
}

#4.5.2 Payment Webhook

Sample Payment Webhook Payload
{
"event": "BILL_PAY",
"timeStamp": "2024-11-26T03:34:50.784Z",
"data": {
"additionalInfo": [],
"billerRefId": "AB123456",
"paymentDetails": {
"amount": 2200,
"mode": "UPI",
"paymentRefId": "2727513156LjQBKlR",
"timestamp": "2024-11-26T03:34:50.784Z"
},
"refId": "CT2K3MHK2D2FSSSIAU30AqF86fl43310904",
"status": "Success",
"transactionId": "DP014331090450ttHQY8"
}
}


#5. Pattern 2: Personalized Options

What this means: Plans are customized based on the user's account and only shown after account validation.

#5.1 Examples of This Pattern

ServiceWhat User EntersWhat User Gets
You BroadbandUsername/Account NumberPlans available for their connection
Airtel Wi-FiBroadband ID/LandlineRecharge options for their specific plan

#5.2 Step 1: Validate Account (Without Plan Selection)

Validate customer account without requiring plan selection upfront.

Request: POST /api/v2/bbps/bills/fetch/request

Sample Request
{
"agent": {},
"customer": {
"mobile": "8484943411",
"customerParams": [
{
"name": "Username / Account No.",
"value": "1234"
}
]
},
"biller": {
"id": "BILLER_ID"
}
}

Response:

Sample Response
{
"data": {
"refId": "CSJ1BPJEA37IGH20GILGDfl3qOd43071737"
},
"success": true,
"traceId": "CSJ1BPJEA37IGH20GIL0"
}

#5.3 Step 2: Get Personalized Plans from Validation Response

Request: POST /api/v2/bbps/bills/fetch/response

Sample Request
{
"refId": "CSJ1BPJEA37IGH20GILGDfl3qOd43071737"
}

Response with Dynamic Plans:

Sample Response
{
"success": true,
"traceId": "CR3J63KR22BP6FC8N9B0",
"data": {
"additionalInfo": [],
"billerRefId": "ABCD1234",
"exactness": "Any",
"refId": "CSJ1BPJEA37IGH20GILGDfl3qOd43071737",
"status": "Success",
"billerPlanResponse": {
"planInfo": [
{
"type": "RECOMMENDED",
"details": [
{
"name": "Plan_ID",
"value": "1"
},
{
"name": "Plan_Amount_In_Rupees",
"value": "599"
},
{
"name": "Plan_Description",
"value": "Unlimited Data"
},
{
"name": "Plan_Validity",
"value": "28 Days"
}
]
}
]
}
}
}

#5.3.1 Validation Webhook with Plans

Sample Validation Webhook Payload
{
"event": "BILL_VALIDATE",
"timeStamp": "2024-11-26T08:06:44.060+05:30",
"data": {
"additionalInfo": [],
"billerRefId": "836480286",
"exactness": "Any",
"refId": "CT2J8EPK2D2FSSRG91EGNXTEK4U43310806",
"status": "Success",
"billerPlanResponse": {
"planInfo": [
{
"type": "RECOMMENDED",
"details": [
{
"name": "Plan_ID",
"value": "1"
},
{
"name": "Plan_Amount_In_Rupees",
"value": "599"
},
{
"name": "Plan_Description",
"value": "Unlimited Data"
},
{
"name": "Plan_Validity",
"value": "28 Days"
}
]
}
]
}
}
}

#5.4 Step 3: Process Payment with Selected Plan

Process payment including the selected plan ID in payment details.

Request: POST /api/v2/bbps/bills/payment/request

Sample Request
{
"refId": "CSJ1BPJEA37IGH20GILGDfl3qOd43071737",
"paymentDetails": {
"mode": "Debit Card",
"paymentRefId": "1zw2B959aLpxqv",
"timestamp": "2024-11-18T19:12:05+05:30",
"amount": 2200,
"Id": "1"
}
}

Response:

Sample Response
{
"data": {
"refId": "CSJ1BPJEA37IGH20GILGDfl3qOd43071737"
},
"success": true,
"traceId": "CSJ1BRREA37IGH20GIO0"
}

#5.4.1 Check Payment Status

Request: POST /api/v2/bbps/bills/payment/response

Sample Request
{
"refId": "CSJ1BPJEA37IGH20GILGDfl3qOd43071737"
}

Response with Plan ID:

Sample Response
{
"success": true,
"traceId": "CSJ1BSREA37IGH20GIQ0",
"data": {
"additionalInfo": [],
"billerRefId": "8925477974299500719",
"paymentDetails": {
"amount": 2200,
"mode": "Debit Card",
"paymentRefId": "REZYOXmwbDF3bx",
"timestamp": "2024-11-02T17:37:11.000+05:30",
"Id": "1"
},
"refId": "CSJ1BPJEA37IGH20GILGDfl3qOd43071737",
"status": "Success",
"transactionId": "DP014307173711LO95Q9"
}
}

#5.4.2 Payment Webhook with Plan ID

It is similar to this webhook but with added plan details:

Sample Webhook Payload
{
"event": "BILL_PAY",
"timeStamp": "2024-11-26T03:34:50.784Z",
"data": {
"additionalInfo": [],
"billerRefId": "AB123456",
"paymentDetails": {
"amount": 2200,
"mode": "UPI",
"paymentRefId": "2727513156LjQBKlR",
"timestamp": "2024-11-26T03:34:50.784Z",
+ "Id": "1"
},
"refId": "CT2K3MHK2D2FSSSIAU30AqF86fl43310904",
"status": "Success",
"transactionId": "DP014331090450ttHQY8"
},
"success": true,
"traceId": "C3SFG0O6N88R6UI7EQ",
}


Was this page helpful?