Subscriptions in Cashfree
Subscription Integration
Section titled “Subscription Integration”This document provides a detailed description for creating subscriptions used for integrating with Cashfree Payments - Subscription APIs (v2025-01-01), including data flow, constraints, validation, and backend responsibilities.
1. Overview
Section titled “1. Overview”When creating a subscription using Cashfree APIs, the system must:
- Collect subscription details from frontend (customer, plan, authorization).
- Validate and store the data internally.
- Generate a unique
subscription_id. - Prepare the Cashfree-compliant payload.
- Send the API request and store the returned status and metadata.
- Handle authorization flow (mandate creation).
- Track subscription lifecycle and payment schedules.
Key Characteristics:
- Mandate-based: Requires authorization (eNACH, pNACH, UPI, Card) before recurring charges.
- Plan Types: Supports PERIODIC (fixed intervals) and ON_DEMAND (variable amounts) plans.
- Multiple Payment Methods: eNACH, pNACH, UPI, and Card for authorization.
- Async Authorization: Authorization process is async, requires status tracking.
- Payment Scheduling: Automatic payment processing based on plan configuration.
2. Data Flow Summary
Section titled “2. Data Flow Summary”Step 1 — Frontend Input (Raw User Inputs)
Section titled “Step 1 — Frontend Input (Raw User Inputs)”{ "customer_name": "John Doe", "customer_email": "[email protected]", "customer_phone": "9908730221", "customer_bank_account_number": "59108290701802", "customer_bank_ifsc": "HDFC0002614", "customer_bank_code": "HDFC", "customer_bank_account_type": "SAVINGS", "plan_name": "Monthly Premium", "plan_type": "PERIODIC", "plan_amount": 1000.0, "plan_max_amount": 5000.0, "plan_max_cycles": 12, "plan_intervals": 1, "plan_interval_type": "MONTH", "authorization_amount": 1.0, "payment_methods": ["enach", "upi", "card"]}Step 2 — Backend Validates & Stores Preliminary Data
Section titled “Step 2 — Backend Validates & Stores Preliminary Data”- Validate customer details (email, phone, bank details if provided).
- Validate plan configuration (amounts, intervals, cycles).
- Validate authorization details.
- Create DB entry with status =
INITIALIZED.
Step 3 — Prepare Cashfree Payload
Section titled “Step 3 — Prepare Cashfree Payload”Mapped fields:
- Customer details →
customer_details - Plan configuration →
plan_details - Authorization →
authorization_details - Metadata →
subscription_meta - System-generated →
subscription_id
Step 4 — Send to Cashfree API
Section titled “Step 4 — Send to Cashfree API”POST /pg/subscriptions
Step 5 — Store Cashfree Response
Section titled “Step 5 — Store Cashfree Response”Save:
cf_subscription_id(Cashfree’s unique subscription ID)subscription_statussubscription_session_id(for authorization flow)authorisation_details(authorization status and payment method details)next_schedule_date(for PERIODIC plans)
Step 6 — Handle Authorization Flow
Section titled “Step 6 — Handle Authorization Flow”- Redirect customer to authorization URL (if link-based).
- Handle webhook callbacks for authorization status.
- Update subscription status based on authorization result.
3. Database Schema
Section titled “3. Database Schema”3.1 Customers Table
Section titled “3.1 Customers Table”| Column | Type | Description | Notes |
|---|---|---|---|
id | BIGINT PK | Internal unique customer ID | Auto-increment |
customer_name | VARCHAR | Customer’s display name | From frontend |
customer_email | VARCHAR | Customer email | Unique, required |
customer_phone | VARCHAR | Customer phone | Required |
customer_bank_account_number | VARCHAR | Bank account number | Optional |
customer_bank_ifsc | VARCHAR | IFSC code | Optional |
customer_bank_code | VARCHAR | Bank code | Optional |
customer_bank_account_type | VARCHAR | Account type (SAVINGS/CURRENT) | Optional |
customer_bank_account_holder_name | VARCHAR | Account holder name | Optional, max 40 chars |
created_at | TIMESTAMP | Row creation time | Auto |
updated_at | TIMESTAMP | Row update time | Auto |
Purpose
Section titled “Purpose”The customers table stores customer information. Can be reused across multiple subscriptions.
3.2 Plans Table
Section titled “3.2 Plans Table”| Column | Type | Description | Notes |
|---|---|---|---|
id | BIGINT PK | Internal primary key | Auto-increment |
plan_id | VARCHAR UNIQUE | Unique plan identifier | Merchant-provided or generated |
plan_name | VARCHAR | Plan name | Required |
plan_type | VARCHAR | PERIODIC or ON_DEMAND | Required |
plan_currency | VARCHAR | Currency code | Default: INR |
plan_amount | DECIMAL(18,2) | Recurring amount (PERIODIC) | Required for PERIODIC |
plan_max_amount | DECIMAL(18,2) | Maximum amount per charge | Required |
plan_max_cycles | INTEGER | Maximum payment cycles | 0 for unlimited (ON_DEMAND) |
plan_intervals | INTEGER | Number of intervals | Required for PERIODIC |
plan_interval_type | VARCHAR | DAY/WEEK/MONTH/YEAR | Required for PERIODIC |
plan_note | TEXT | Plan description/notes | Optional |
plan_status | VARCHAR | ACTIVE/INACTIVE | Default: ACTIVE |
created_at | TIMESTAMP | Auto | |
updated_at | TIMESTAMP | Auto |
Key Design Notes
Section titled “Key Design Notes”- Plans can be reused across multiple subscriptions.
plan_idshould be unique and stable.- For ON_DEMAND plans:
plan_amount= 0,plan_max_cycles= 0.
3.3 Subscriptions Table
Section titled “3.3 Subscriptions Table”| Column | Type | Description | Notes |
|---|---|---|---|
id | BIGINT PK | Internal primary key | Auto-increment |
customer_id | BIGINT FK | FK → customers.id | Required |
plan_id | BIGINT FK | FK → plans.id | Required |
subscription_id | VARCHAR UNIQUE | Unique ID sent to Cashfree | Must never change once created |
cf_subscription_id | VARCHAR | Cashfree’s subscription ID | From Cashfree response |
subscription_status | VARCHAR | Subscription status | INITIALIZED/ACTIVE/PAUSED/CANCELLED/etc |
subscription_session_id | VARCHAR | Session ID for authorization | From Cashfree response |
authorization_status | VARCHAR | Authorization status | INITIALIZED/SUCCESS/FAILED |
authorization_amount | DECIMAL(18,2) | Authorization amount | Usually 1.0 |
authorization_amount_refund | BOOLEAN | Whether to refund auth amount | Default: false |
payment_group | VARCHAR | Payment method group | enach/pnach/upi/card |
payment_method_details | JSON | Payment method specific details | From Cashfree response |
subscription_expiry_time | TIMESTAMP | Subscription expiry | From Cashfree |
subscription_first_charge_time | TIMESTAMP | First charge time (PERIODIC) | From Cashfree |
next_schedule_date | TIMESTAMP | Next payment schedule | From Cashfree, null for ON_DEMAND |
return_url | VARCHAR | Return URL after authorization | Optional |
notification_channel | JSON | Notification preferences | EMAIL/SMS |
session_id_expiry | TIMESTAMP | Authorization session expiry | From Cashfree |
subscription_tags | JSON | Custom tags | Optional |
subscription_note | TEXT | Subscription notes | Optional |
raw_request | JSON | Full request payload | Helpful for audits |
raw_response | JSON | Full Cashfree response | Helpful for audits |
created_at | TIMESTAMP | Auto | |
updated_at | TIMESTAMP | Auto |
Key Design Notes
Section titled “Key Design Notes”subscription_idmust be unique, stable, deterministic (max length varies).- Link to
customersandplanstables via foreign keys. - Store complete authorization details for mandate tracking.
next_schedule_dateis null for ON_DEMAND plans.
3.4 Subscription Payments Table (Optional)
Section titled “3.4 Subscription Payments Table (Optional)”| Column | Type | Description | Notes |
|---|---|---|---|
id | BIGINT PK | Internal primary key | Auto-increment |
subscription_id | BIGINT FK | FK → subscriptions.id | Required |
payment_id | VARCHAR | Cashfree payment ID | From Cashfree |
payment_amount | DECIMAL(18,2) | Payment amount | |
payment_status | VARCHAR | Payment status | SUCCESS/FAILED/PENDING |
payment_utr | VARCHAR | Unique Transaction Reference | From bank/Cashfree |
scheduled_date | TIMESTAMP | Scheduled payment date | |
processed_at | TIMESTAMP | Actual processing time | |
cycle_number | INTEGER | Payment cycle number | 1, 2, 3, etc. |
raw_response | JSON | Full payment response | Helpful for audits |
created_at | TIMESTAMP | Auto | |
updated_at | TIMESTAMP | Auto |
Purpose
Section titled “Purpose”Track individual payment attempts within a subscription for reconciliation and reporting.
4. Plan Types & Configuration
Section titled “4. Plan Types & Configuration”4.1 PERIODIC Plans
Section titled “4.1 PERIODIC Plans”Characteristics:
- Fixed recurring amount at regular intervals.
- Automatic payment processing.
- Requires
plan_amount,plan_intervals,plan_interval_type.
Example Configuration:
{ "plan_type": "PERIODIC", "plan_amount": 1000.0, "plan_max_amount": 1000.0, "plan_max_cycles": 12, "plan_intervals": 1, "plan_interval_type": "MONTH"}Interval Types:
DAY: Daily subscriptionsWEEK: Weekly subscriptionsMONTH: Monthly subscriptionsYEAR: Yearly subscriptions
Use Cases:
- Monthly membership fees
- Weekly service charges
- Annual subscription plans
4.2 ON_DEMAND Plans
Section titled “4.2 ON_DEMAND Plans”Characteristics:
- Variable payment amounts (up to
plan_max_amount). - Manual or API-triggered charges.
- No automatic scheduling.
Example Configuration:
{ "plan_type": "ON_DEMAND", "plan_amount": 0.0, "plan_max_amount": 50000.0, "plan_max_cycles": 0, "plan_intervals": 0, "plan_interval_type": ""}Use Cases:
- Variable utility bill payments
- Top-up services
- Pay-as-you-go models
5. Authorization & Payment Methods
Section titled “5. Authorization & Payment Methods”5.1 Supported Payment Methods
Section titled “5.1 Supported Payment Methods”| Payment Method | Description | Channel Type | Authorization Flow |
|---|---|---|---|
enach | Electronic NACH (eMandate) | link | Redirect to NetBanking for mandate |
pnach | Physical NACH (Paper mandate) | post | Upload physical mandate form |
upi | UPI AutoPay | collect | UPI authorization via app |
card | Card Tokenization | link | Card authorization via payment page |
5.2 Authorization Amount
Section titled “5.2 Authorization Amount”- Purpose: Verify mandate and validate bank account/card.
- Typical Value:
1.0(INR 1) - Refund Option:
authorization_amount_refund: trueto refund after successful authorization.
5.3 Authorization Flow
Section titled “5.3 Authorization Flow”eNACH (Link-based)
Section titled “eNACH (Link-based)”- Customer redirected to NetBanking authorization page.
- Customer authenticates and approves mandate.
- Webhook callback with authorization status.
- Subscription status updated to
ACTIVEon success.
pNACH (Physical)
Section titled “pNACH (Physical)”- Physical mandate form uploaded via API.
- Cashfree processes the form.
- Webhook callback when mandate is registered.
- Subscription status updated accordingly.
UPI (Collect)
Section titled “UPI (Collect)”- UPI authorization request sent to customer’s UPI app.
- Customer approves in UPI app.
- Webhook callback with authorization status.
Card (Link)
Section titled “Card (Link)”- Customer redirected to card authorization page.
- Customer enters card details and approves.
- Card tokenized and stored.
- Webhook callback with authorization status.
5.4 UI Flow for Subscription Authorization
Section titled “5.4 UI Flow for Subscription Authorization”Important: The authorization UI flow is identical for both PERIODIC and ON_DEMAND plans. The plan type only affects how payments are triggered after authorization, not the authorization process itself.
Step-by-Step UI Flow
Section titled “Step-by-Step UI Flow”1. Frontend Initiates Subscription
Section titled “1. Frontend Initiates Subscription”- User fills subscription form (customer details, plan selection).
- Frontend sends request to your backend.
2. Backend Creates Subscription
Section titled “2. Backend Creates Subscription”- Backend calls Cashfree API:
POST /pg/subscriptions - Response received with
subscription_status: "INITIALIZED"andauthorisation_details
3. Authorization UI (Based on Payment Method)
Section titled “3. Authorization UI (Based on Payment Method)”For eNACH (Link-based):
User's Browser → Your Backend → Cashfree API ↓ Response with authorization URL ↓User's Browser ← Redirect to Cashfree NetBanking Page ↓User authenticates and approves mandate ↓User's Browser ← Redirect back to YOUR APP's return_url ↓Your App's return_url endpoint → Verify status via API ↓Webhook → Your Backend (authorization status - more reliable)What User Sees:
- Redirected to Cashfree-hosted NetBanking page
- User logs into their bank account
- User approves the mandate/eMandate
- Redirected back to your
return_url
For Card (Link-based):
User's Browser → Your Backend → Cashfree API ↓ Response with authorization URL ↓User's Browser ← Redirect to Cashfree Card Authorization Page ↓User enters card details and approves ↓User's Browser ← Redirect back to YOUR APP's return_url ↓Your App's return_url endpoint → Verify status via API ↓Webhook → Your Backend (authorization status - more reliable)What User Sees:
- Redirected to Cashfree-hosted card payment page
- User enters card number, CVV, expiry
- User approves authorization
- Redirected back to your
return_url
For UPI (Collect-based):
User's Browser → Your Backend → Cashfree API ↓ Response with UPI authorization details ↓User's Browser ← Shows "Approve in UPI App" message ↓User's UPI App ← Receives collect request ↓User approves in UPI app ↓Webhook → Your Backend (authorization status)What User Sees:
- No redirect to Cashfree UI
- UPI collect request appears in user’s UPI app (PhonePe, Google Pay, etc.)
- User approves in UPI app
- Your frontend can poll or wait for webhook to update status
For pNACH (Physical):
User's Browser → Your Backend → Cashfree API ↓ Response with subscription_id ↓User uploads physical mandate form (separate API call) ↓Cashfree processes form (async, can take days) ↓Webhook → Your Backend (authorization status)What User Sees:
- No immediate UI interaction
- Physical form upload happens separately
- Status updates via webhook when processed
4. Post-Authorization UI
Section titled “4. Post-Authorization UI”After Successful Authorization:
For PERIODIC Plans:
- Show success message: “Subscription activated! First payment scheduled for [date]”
- Display subscription details and next payment date
- Payments happen automatically - no further UI needed
For ON_DEMAND Plans:
- Show success message: “Authorization successful! You can now make payments.”
- Display subscription details
- Important: No automatic payments - user or your system must trigger charges via API
- Show “Make Payment” button or trigger charges programmatically
5. Getting Authorization URL
Section titled “5. Getting Authorization URL”For Link-based Methods (eNACH, Card):
The authorization URL is typically constructed using:
subscription_session_idfrom the response- Cashfree’s authorization endpoint
Example Flow:
// Backend receives responseconst response = { subscription_session_id: "subs_token_tc9JCN4MzUIJ", authorisation_details: { payment_group: "enach", // ... other details },};
// Construct authorization URLconst authUrl = `https://payments.cashfree.com/subscription/auth/${response.subscription_session_id}`;
// Redirect userwindow.location.href = authUrl;Key Differences: PERIODIC vs ON_DEMAND
Section titled “Key Differences: PERIODIC vs ON_DEMAND”| Aspect | PERIODIC | ON_DEMAND |
|---|---|---|
| Authorization UI | Same (eNACH/Card/UPI/pNACH) | Same (eNACH/Card/UPI/pNACH) |
| After Authorization | Automatic payments start | Manual/API-triggered payments |
| User Action After Auth | None (automatic) | Trigger charges when needed |
| UI After Auth | Show schedule, wait for payments | Show “Pay Now” or trigger via API |
Important Notes
Section titled “Important Notes”-
ON_DEMAND subscriptions still require authorization - the mandate must be created before any charges can be made.
-
Authorization is one-time - once authorized, you can make multiple charges (up to
plan_max_amount) without additional UI interaction. -
No Cashfree UI for charges - After authorization, ON_DEMAND charges are triggered via API calls. There’s no payment page for individual charges.
-
Return URL handling - The
return_urlis your application’s URL where Cashfree redirects the user after authorization (for link-based methods like eNACH and Card).Implementation:
// In your subscription creation request{"subscription_meta": {"return_url": "https://yourapp.com/subscription/authorization/return"}}Handle the return in your app:
// Example: /subscription/authorization/return endpoint// Cashfree will redirect here with query parameters// GET /subscription/authorization/return?subscription_id=SUB_42_1702259812&status=SUCCESS// Your backend should:// 1. Extract subscription_id from query params// 2. Verify authorization status via Cashfree API or webhook// 3. Update your database// 4. Show appropriate UI (success/failure page)// Example backend handler:app.get("/subscription/authorization/return", async (req, res) => {const { subscription_id, status } = req.query;// Verify status with Cashfree APIconst subscription = await cashfree.getSubscription(subscription_id);// Update your databaseawait db.updateSubscription(subscription_id, {subscription_status: subscription.subscription_status,authorization_status:subscription.authorisation_details.authorization_status,});// Redirect to frontend success/failure pageif (subscription.authorisation_details.authorization_status === "SUCCESS") {res.redirect(`/subscription/success?subscription_id=${subscription_id}`);} else {res.redirect(`/subscription/failed?subscription_id=${subscription_id}`);}});Important:
- The
return_urlmust be publicly accessible (not localhost in production) - Cashfree will append query parameters to your URL
- Always verify the authorization status via API call, don’t trust query params alone
- Webhooks are more reliable than return_url for status updates (use both)
- The
6. Backend Behavior & Error Handling
Section titled “6. Backend Behavior & Error Handling”6.1 On Create Request
Section titled “6.1 On Create Request”- Validate customer, plan, and authorization details.
- Generate unique
subscription_id. - Save subscription → status =
INITIALIZED. - Call Cashfree API.
- Update:
cf_subscription_idsubscription_statussubscription_session_idauthorisation_detailsnext_schedule_date(if PERIODIC)
6.2 Authorization Handling
Section titled “6.2 Authorization Handling”If authorization is link-based (eNACH, Card):
- Store
subscription_session_id. - Redirect customer to authorization URL.
- Handle return via
return_url. - Process webhook for final authorization status.
If authorization is collect-based (UPI):
- Store authorization details.
- Wait for webhook callback.
- Update subscription status on webhook.
If authorization is post-based (pNACH):
- Upload physical mandate form separately.
- Wait for webhook callback after processing.
6.3 Status Updates
Section titled “6.3 Status Updates”Common subscription statuses:
INITIALIZED: Subscription created, authorization pendingACTIVE: Authorization successful, subscription activePAUSED: Subscription paused (can be resumed)CANCELLED: Subscription cancelledCOMPLETED: All cycles completed or expiredEXPIRED: Subscription expired
6.4 Idempotency
Section titled “6.4 Idempotency”If frontend retries:
- Use the same
subscription_idto prevent duplicate subscriptions. - Check if
subscription_idalready exists in database. - If exists, return existing subscription record.
6.5 Payment Processing
Section titled “6.5 Payment Processing”For PERIODIC plans:
- Cashfree automatically processes payments based on schedule.
- Webhook callbacks for each payment attempt.
- Update
next_schedule_dateafter each payment.
For ON_DEMAND plans:
- Trigger charges via API when needed.
- Use subscription ID to initiate charges.
- Track each charge separately.
7. Cashfree Payload Mapping
Section titled “7. Cashfree Payload Mapping”Outbound Request (PERIODIC Plan)
Section titled “Outbound Request (PERIODIC Plan)”{ "subscription_id": "SUB_42_1702259812", "customer_details": { "customer_name": "John Doe", "customer_email": "[email protected]", "customer_phone": "9908730221", "customer_bank_account_number": "59108290701802", "customer_bank_ifsc": "HDFC0002614", "customer_bank_code": "HDFC", "customer_bank_account_type": "SAVINGS" }, "plan_details": { "plan_name": "Monthly Premium Plan", "plan_type": "PERIODIC", "plan_amount": 1000.0, "plan_max_amount": 1000.0, "plan_max_cycles": 12, "plan_intervals": 1, "plan_currency": "INR", "plan_interval_type": "MONTH", "plan_note": "Monthly subscription for premium features" }, "authorization_details": { "authorization_amount": 1.0, "authorization_amount_refund": true, "payment_methods": ["enach", "upi", "card"] }, "subscription_meta": { "return_url": "https://yourapp.com/subscription/return", "notification_channel": ["EMAIL", "SMS"], "session_id_expiry": "2025-06-01T23:00:08+05:30" }, "subscription_expiry_time": "2026-12-31T23:59:59+05:30", "subscription_first_charge_time": "2025-02-01T10:00:00+05:30", "subscription_tags": { "psp_note": "Monthly subscription payment", "plan_tier": "premium" }}Outbound Request (ON_DEMAND Plan)
Section titled “Outbound Request (ON_DEMAND Plan)”{ "subscription_id": "SUB_42_1702259813", "customer_details": { "customer_name": "Jane Smith", "customer_email": "[email protected]", "customer_phone": "9876543210" }, "plan_details": { "plan_name": "On Demand Utility Plan", "plan_type": "ON_DEMAND", "plan_amount": 0.0, "plan_max_amount": 50000.0, "plan_max_cycles": 0, "plan_intervals": 0, "plan_currency": "INR", "plan_interval_type": "", "plan_note": "Variable amount utility payments" }, "authorization_details": { "authorization_amount": 1.0, "authorization_amount_refund": true, "payment_methods": ["enach", "upi"] }, "subscription_meta": { "return_url": "https://yourapp.com/subscription/return", "notification_channel": ["EMAIL"] }, "subscription_expiry_time": "2100-01-01T23:59:59+05:30"}Inbound Response (eNACH Authorization)
Section titled “Inbound Response (eNACH Authorization)”{ "subscription_id": "SUB_42_1702259812", "cf_subscription_id": "4", "subscription_status": "INITIALIZED", "subscription_session_id": "subs_token_tc9JCN4MzUIJ", "authorisation_details": { "authorization_amount": 1.0, "authorization_amount_refund": false, "authorization_reference": "", "authorization_time": "2025-06-01T23:47:52+05:30", "authorization_status": "INITIALIZED", "payment_id": "97877", "payment_group": "enach", "payment_method": { "enach": { "channel": "link", "auth_mode": "NetBanking", "account_type": "SAVINGS", "account_number": "123456789012", "account_ifsc": "SBIN0000123", "account_holder_name": "John Doe", "account_bank_code": "SBIN" } } }, "customer_details": { "customer_name": "John Doe", "customer_email": "[email protected]", "customer_phone": "9900755700" }, "plan_details": { "plan_name": "Monthly Premium Plan", "plan_type": "PERIODIC", "plan_amount": 1000.0, "plan_max_amount": 1000.0, "plan_max_cycles": 12, "plan_intervals": 1, "plan_interval_type": "MONTH", "plan_currency": "INR" }, "next_schedule_date": "2025-02-01T10:00:00+05:30", "subscription_expiry_time": "2026-12-31T23:59:59+05:30", "subscription_first_charge_time": "2025-02-01T10:00:00+05:30", "subscription_meta": { "return_url": "https://yourapp.com/subscription/return" }}Inbound Response (UPI Authorization)
Section titled “Inbound Response (UPI Authorization)”{ "subscription_id": "SUB_42_1702259814", "cf_subscription_id": "5", "subscription_status": "INITIALIZED", "subscription_session_id": "subs_token_xyz123", "authorisation_details": { "authorization_amount": 1.0, "authorization_amount_refund": false, "authorization_status": "INITIALIZED", "payment_id": "97878", "payment_group": "upi", "payment_method": { "upi": { "channel": "collect", "upi_id": "test@upi", "upi_instrument": "upiInstrument", "upi_instrument_number": "1234567890", "upi_payer_account_number": "039861903074", "upi_payer_ifsc": "SBIN0001234" } } }, "customer_details": { "customer_name": "Jane Smith", "customer_email": "[email protected]", "customer_phone": "9876543210" }, "plan_details": { "plan_name": "Weekly Service Plan", "plan_type": "PERIODIC", "plan_amount": 500.0, "plan_max_amount": 500.0, "plan_max_cycles": 52, "plan_intervals": 1, "plan_interval_type": "WEEK", "plan_currency": "INR" }, "next_schedule_date": "2025-02-08T10:00:00+05:30", "subscription_expiry_time": "2026-12-31T23:59:59+05:30"}8. Important Notes
Section titled “8. Important Notes”8.1 Authorization Flow
Section titled “8.1 Authorization Flow”- Link-based (eNACH, Card): Customer must complete authorization via redirect.
- Collect-based (UPI): Authorization happens via UPI app, no redirect needed.
- Post-based (pNACH): Requires separate file upload API call.
8.2 Session Expiry
Section titled “8.2 Session Expiry”session_id_expirysets when authorization session expires.- Customer must complete authorization before expiry.
- Extend session if needed or create new subscription.
8.3 Subscription Expiry
Section titled “8.3 Subscription Expiry”subscription_expiry_timesets when subscription expires.- Set far in future (e.g., 2100-01-01) for long-term subscriptions.
- Expired subscriptions cannot process new payments.
8.4 First Charge Time
Section titled “8.4 First Charge Time”subscription_first_charge_timeapplies only to PERIODIC plans.- Must be in the future.
- Subsequent charges calculated based on
plan_interval_type.
8.5 Payment Methods Priority
Section titled “8.5 Payment Methods Priority”- If multiple
payment_methodsprovided, Cashfree selects based on availability. - Customer may choose preferred method during authorization.
- Store selected method for future reference.
8.6 TPV (Third Party Verification)
Section titled “8.6 TPV (Third Party Verification)”- For TPV transactions,
customer_bank_account_holder_nameis mandatory. - At least one of
customer_bank_codeorcustomer_bank_ifscrequired. - Helps verify account ownership.
8.7 Notification Channels
Section titled “8.7 Notification Channels”EMAIL: Email notifications for subscription events.SMS: SMS notifications for subscription events.- Can specify both for comprehensive notifications.
8.8 Payment Splits
Section titled “8.8 Payment Splits”- Optional
subscription_payment_splitsfor vendor splits. - Specify
vendor_idandpercentage. - Applies to all payments in the subscription.
8.9 Return URL Configuration
Section titled “8.9 Return URL Configuration”return_urlis YOUR application’s URL - not Cashfree’s URL.- Cashfree redirects users back to this URL after authorization (for link-based methods).
- Must be publicly accessible (HTTPS in production).
- Example:
https://yourapp.com/subscription/authorization/return - Cashfree appends query parameters:
?subscription_id=SUB_XXX&status=SUCCESS - Always verify status via API - don’t trust query parameters alone for security.
- Webhooks are more reliable for status updates (use both return_url and webhooks).
9. API Endpoints Reference
Section titled “9. API Endpoints Reference”Create Subscription
Section titled “Create Subscription”Endpoint: POST /pg/subscriptions
Base URLs:
- Sandbox:
https://sandbox.cashfree.com/pg - Production:
https://api.cashfree.com/pg
Required Headers:
x-api-version: 2025-01-01(or latest)x-client-id: <api-key>x-client-secret: <api-key>Content-Type: application/json
Optional Headers:
x-request-id: <unique-request-id>(for tech support)
Fetch Subscription
Section titled “Fetch Subscription”Endpoint: GET /pg/subscriptions/{subscription_id}
Use this to check the current status of a subscription.
Manage Subscription
Section titled “Manage Subscription”Endpoint: POST /pg/subscriptions/{subscription_id}
Use this to pause, resume, or cancel a subscription.
10. Response Codes Reference
Section titled “10. Response Codes Reference”| HTTP Status | Status | Description | Next Action |
|---|---|---|---|
| 200 | INITIALIZED | Subscription created, authorization pending | Redirect customer to authorization or wait for webhook |
| 200 | ACTIVE | Subscription active, payments processing | Monitor payments via webhooks |
| 400 | - | Bad request (validation error) | Check request payload and fix validation errors |
| 401 | - | Unauthorized (authentication error) | Verify API credentials |
| 404 | - | Resource not found | Verify subscription_id or plan_id |
| 422 | - | Unprocessable entity (business logic error) | Check plan configuration and constraints |
| 429 | - | Rate limit exceeded | Retry after rate limit window |
| 500 | - | Internal server error | Retry with exponential backoff |
11. Subscription Lifecycle
Section titled “11. Subscription Lifecycle”State Transitions
Section titled “State Transitions”INITIALIZED → (Authorization Success) → ACTIVEINITIALIZED → (Authorization Failed) → CANCELLEDACTIVE → (Pause Request) → PAUSEDPAUSED → (Resume Request) → ACTIVEACTIVE → (Cancel Request) → CANCELLEDACTIVE → (All Cycles Complete) → COMPLETEDACTIVE → (Expiry Time Reached) → EXPIREDAuthorization Status
Section titled “Authorization Status”INITIALIZED: Authorization initiatedSUCCESS: Authorization completed successfullyFAILED: Authorization failedPENDING: Authorization in progress
13. Webhook Events
Section titled “13. Webhook Events”Authorization Webhooks
Section titled “Authorization Webhooks”subscription.authorized: Authorization successfulsubscription.authorization_failed: Authorization failed
Payment Webhooks
Section titled “Payment Webhooks”subscription.payment_success: Payment processed successfullysubscription.payment_failed: Payment failedsubscription.payment_pending: Payment pending
Subscription Webhooks
Section titled “Subscription Webhooks”subscription.activated: Subscription activatedsubscription.paused: Subscription pausedsubscription.resumed: Subscription resumedsubscription.cancelled: Subscription cancelledsubscription.completed: Subscription completedsubscription.expired: Subscription expired
Important: Implement webhook signature verification for security.