Webhook Handling


In a subscription-based system, it’s essential to confirm the outcome of every payment event. Once a payment or recurring debit is initiated, your system should quickly identify whether it was successful, failed, or is still pending. This real-time verification helps you take timely actions like activating services, updating customer access, retrying failed payments, or sending notifications.

To support this, PhonePe sends two types of webhook callbacks that your system should listen to:

  • Subscription Callbacks: These indicate the result of the first payment made when a subscription is created.
  • Redemption Callbacks: These provide the status of automated payments for ongoing subscriptions.

To start receiving essential subscription status updates in real-time, you’ll need to set up your Webhook callback. This ensures our system can notify yours about changes. To enable these crucial updates, you’ll configure the following:

  • Callback URL: Your server endpoint where PhonePe will send subscription updates.
  • Username: Create and set your own username.
  • Password: Create and set your own password.

Make sure the same username and password are used in your code to validate the Authorization header received in the callback from PhonePe.

For incoming requests, extract the Authorization header, validate it against the username:password you configured with us, and accept the response only if the values match.
Authorization: SHA256(username:password)

FlowCallback Type
Setupsubscription.setup.order.completed
subscription.setup.order.failed
Redemptionsubscription.redemption.order.completed
subscription.redemption.order.failed
Redemption Cancelsubscription.redemption.order.cancelled
Subscription Setup Order: COMPLETED
{
    "type": "SUBSCRIPTION_SETUP_ORDER_COMPLETED",
    "event": "subscription.setup.order.completed",
    "payload": {
        "merchantId": "TX12345",
        "merchantOrderId": "MO1774243061089",
        "orderId": "OMO2603231047412984235557BW",
        "state": "PENDING",
        "currency": "INR",
        "amount": 200,
        "expireAt": 1774243961270,
        "metaInfo": {
            "udf1": "udf1",
            "udf2": "udf2"
        },
        "paymentFlow": {
            "type": "SUBSCRIPTION_SETUP",
            "merchantSubscriptionId": "MS1774243061089",
            "authWorkflowType": "ZERO",
            "amountType": "FIXED",
            "maxAmount": 20000000,
            "frequency": "MONTHLY",
            "expireAt": 1774643045000,
            "subscriptionId": "OMS2603231047412704235838BW",
            "productType": "ENACH_MANDATE",
            "authInstrumentType": "NET_BANKING"
        },
        "paymentDetails": []
    }
}
Redemption Executed: COMPLETED
{
    "type": "SUBSCRIPTION_REDEMPTION_ORDER_COMPLETED",
    "event": "subscription.redemption.order.completed",
    "payload": {
    "merchantId": "TX12345",
    "merchantOrderId": "MO1722319560997",
    "orderId": "OMO2601282154473535900531",
    "state": "COMPLETED",
    "currency": "INR",
    "amount": 200,
    "expireAt": 1769618686824,
    "paymentFlow": {
        "type": "SUBSCRIPTION_REDEMPTION",
        "merchantSubscriptionId": "MS1769569283073",
        "redemptionRetryStrategy": null,
        "autoDebit": false,
        "validAfter": null,
        "validUpto": null,
        "notifiedAt": null
    },
    "paymentDetails": [
        {
            "transactionId": "OM2601282154486455900694",
            "paymentMode": "ENACH_ACCOUNT",
            "timestamp": 1769617488702,
            "currency": "INR",
            "amount": 200,
            "payableCurrency": "INR",
            "payableAmount": 200,
            "feeCurrency": "INR",
            "feeAmount": 0,
            "state": "COMPLETED",
            "instrument": {
                "type": "ACCOUNT",
                "accountType": "SAVINGS",
                "bankId": "HDFC"
            },
            "rail": {
                "type": "NACH",
                "utr": "ddf5d315-93cd-4019-9137-7bb2ad2ec702"
            },
            "splitInstruments": [
                {
                    "instrument": {
                        "type": "ACCOUNT",
                        "accountType": "SAVINGS",
                        "bankId": "HDFC"
                    },
                    "rail": {
                        "type": "NACH",
                        "utr": "ddf5d315-93cd-4019-9137-7bb2ad2ec702"
                    },
                    "currency": "INR",
                    "amount": 200
                }
            ]
        }
    ]
}
}
Redemption cancel
{
    "type": "SUBSCRIPTION_REDEMPTION_ORDER_CANCELLED",
    "event": "subscription.redemption.order.cancelled",
    "payload": {
        "merchantId": "SWIGGY8",
        "merchantOrderId": "MO1774751396248",
        "orderId": "OMO2603290759596486953861BW",
        "state": "FAILED",
        "currency": "INR",
        "amount": 20000000,
        "expireAt": 1774917000000,
        "paymentFlow": {
            "type": "SUBSCRIPTION_REDEMPTION",
            "merchantSubscriptionId": "MS1773646960613",
            "autoDebit": false
        },
        "paymentDetails": [
            {
                "transactionId": "OM2603290800005236953538BW",
                "paymentMode": "ENACH_ACCOUNT",
                "timestamp": 1774751400561,
                "currency": "INR",
                "amount": 20000000,
                "payableCurrency": "INR",
                "payableAmount": 20000000,
                "feeCurrency": "INR",
                "feeAmount": 0,
                "state": "FAILED",
                "errorCode": "TXN_CANCELLED",
                "detailedErrorCode": "REQUEST_CANCEL_BY_REQUESTER"
            }
        ]
    }
}
Response Parameter
Parameter NameData TypeDescription
merchantIdStringA unique ID assigned to the merchant by the PhonePe system during the onboarding process.
merchantOrderIdStringA unique orderId provided by the merchant when creating the order. This helps in tracking and managing the specific transaction across systems.
orderIdStringAn orderId generated by PhonePe.
stateStringPossible value:
• COMPLETED
• FAILED
• PENDING
amountLongThe amount provided by the merchant in Paise.
expireAtDateTimeRepresents the time in epoch (milliseconds).
errorCodeStringIndicates the reason for the failure.
[PRESENT ONLY IF STATE = FAILED]
detailedErrorCodeStringProvides a detailed explanation for the failure.
MetaInfoArrayContains metadata provided by the merchant.
paymentFlowObjectProvides the detailed information of the subscription.
paymentFlow.typeStringThe type should be set to “SUBSCRIPTION_REDEMPTION” for redemption transactions.
paymentFlow.merchantSubscriptionIdStringA unique subscriptionId provided by the merchant to identify and manage the subscription request.
paymentFlow.amountTypeStringNature of redemption amount
Possible Values:
• FIXED
• VARIABLE
paymentFlow.maxAmountLongSpecifies the maximum amount that can be debited from the customer’s account for each redemption cycle.
paymentFlow.frequencyStringDefines how often the payment will be deducted from the customer’s account.
paymentFlow.subscriptionIdStringA subscriptionId generated by PhonePe to uniquely identify the user’s subscription.
paymentDetailsArrayContains the details of the payment.
Is this article helpful?