#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:
- Get Available Plans ā
GET /api/v2/bbps/billers/plans
- User Selects Plan + Enters Details ā Your app collects both
- Validate Account + Plan ā
POST /api/v2/bbps/bills/fetch/request
(include plan ID) - 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:
- User Enters Account Details ā Your app collects account info
- Validate Account ā
POST /api/v2/bbps/bills/fetch/request
(no plan ID) - Get Custom Plans ā Response includes plans available for this account
- User Selects Plan ā Your app presents the options
- 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
Pattern | When Plans Are Shown | User Flow | Common Examples |
---|---|---|---|
Pattern 1 | Immediately available | Browse plans ā Select ā Enter details ā Pay | Mobile recharge, DTH packages |
Pattern 2 | After account validation | Enter details ā See custom plans ā Select ā Pay | Broadband 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
Service | What User Enters | What User Selects From |
---|---|---|
BSNL/MTNL Mobile | Mobile Number, Circle | Data plans, talk time, combo offers |
Hungama Play | Mobile Number, Email | Monthly, yearly subscription plans |
Sun Direct TV | Subscriber Number | Channel 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:
Field | Description |
---|---|
data.plans | Array containing current page plans |
data.total | Total number of plans matching query |
data.nextPage | URL 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
:
Request | Response | Next Page |
---|---|---|
GET ā¦&limit=1000 | 1000 plans | after=PLAN_1000&limit=1000 |
GET ā¦&after=PLAN_1000 | 1000 plans | after=PLAN_2000&limit=1000 |
GET ā¦&after=PLAN_2000 | 1000 plans | after=PLAN_3000&limit=1000 |
GET ā¦&after=PLAN_3000 | 700 plans | null (complete) |
#4.2.3 Plan Structure
Each plan object contains both mandatory and optional fields:
interface Plan {// Mandatory fieldsId: string; // 1-32 chars, alphanumericcategoryType: string; // 1-100 chars, alphanumericamountInRupees: string; // 1-10 digits, decimals supporteddescription: string; // text with special chars allowedeffectiveFrom: string; // ISO date formateffectiveTo: string; // ISO date formatstatus: "ACTIVE" | "DEACTIVATED";// Optional fieldscategorySubType?: {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
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
Service | What User Enters | What User Gets |
---|---|---|
You Broadband | Username/Account Number | Plans available for their connection |
Airtel Wi-Fi | Broadband ID/Landline | Recharge 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?