Merchants can configure the Webhook/S2S Callback URLs along with username & password.
PROD – Merchants can configure URL, Username and Password on the PhonePe dashboard.
- URL – Merchant’s Webhook URL
- Username – Merchant configure their own username
- Password – Merchant configure their own password
Note: Merchants should ensure the configured username and password is being used in the code to validate the Authorization header.
UAT – Merchants can reach out to the Integration Team.
- Once the username and password is configured, PhonePe will pass the same SHA256 (username:password) as the “Authorization” header in s2s response.
- Merchants should calculate using the same logic and match with the one passed by PhonePe. If both are matching, then the response payload can be consumed by the merchant. Otherwise, merchants should ignore the response.
Callback Validation/Verification
For the incoming request, extract the basic authorization header “Authorization”, verify it with the one which you have shared with us and accept the response if Username and password matches.
Authorization : SHA256(username:password)
Callback Event Types
Flow | Callback Type |
---|---|
Setup | subscription.setup.order.completed subscription.setup.order.failed |
State Change | subscription.paused subscription.unpaused subscription.revoked subscription.cancelled |
Notification (LINK) | subscription.notification.completed subscription.notification.failed |
Redemption (LINK) | subscription.redemption.order.completed subscription.redemption.order.failed subscription.redemption.transaction.completed subscription.redemption.transaction.failed |
Refund (LINK) | pg.refund.accepted pg.refund.completed pg.refund.failed |
Key Notes
- Merchants should rely only on the root level “payload.state” parameter for the status confirmation.
- Avoid Strict Deserialization
- Don’t rely on “type” parameter in the webhook response (This will be deprecated) instead rely on the “event” parameter only for the webhook event name.
- expireAt and timestamp parameters will be a epoch timestamp ( in milliseconds)
Callbacks – Setup
Subscription Setup Completed
Note: Merchants should rely only on the highlighted “payload.state” parameter for the payment status confirmation.
{
"event": "subscription.setup.order.completed",
"payload": {
"merchantId": "SWIGGY8",
"merchantOrderId": "MO1708797962855",
"orderId": "OMO2402242336055135042802",
"state": "COMPLETED",
"amount": 200,
"expireAt": 1708798385505,
"paymentFlow": {
"type": "SUBSCRIPTION_SETUP",
"merchantSubscriptionId": "MS1708797962855",
"authWorkflowType": "TRANSACTION",
"amountType": "FIXED",
"maxAmount": 200,
"frequency": "ON_DEMAND",
"expireAt": 1741345725943,
"subscriptionId": "OMS2502051638460659623138"
},
"paymentDetails": [
{
"transactionId": "OM2402242336055865042862",
"paymentMode": "UPI_INTENT",
"timestamp": 1708797965588,
"amount": 200,
"payableAmount": 200,
"feeAmount": 0,
"state": "COMPLETED",
"instrument": {
"type": "ACCOUNT",
"maskedAccountNumber": "XXXXXXXXXXX0945"
},
"rail": {
"type": "UPI",
"utr": "405554491450",
"vpa": "999@ybl",
"umn": "d519347eb2374125bcad6e69a42cc13b@ybl"
}
}
]
}
}
Subscription Setup Failed
Note: Merchants should rely only on the highlighted “payload.state” parameter for the payment status confirmation.
{
"event": "subscription.setup.order.failed",
"payload": {
"merchantId": "SWIGGY8",
"merchantOrderId": "MO1708797962855",
"orderId": "OMO2402242336055135042802",
"state": "FAILED",
"amount": 200,
"expireAt": 1708798385505,
"errorCode": "INVALID_MPIN",
"detailedErrorCode": "ZM",
"paymentFlow": {
"type": "SUBSCRIPTION_SETUP",
"merchantSubscriptionId": "MS1708797962855",
"authWorkflowType": "TRANSACTION",
"amountType": "FIXED",
"maxAmount": 200,
"frequency": "ON_DEMAND",
"expireAt": 1741345725943,
"subscriptionId": "OMS2502051638460659623138"
},
"paymentDetails": [
{
"transactionId": "OM2402242336055865042862",
"paymentMode": "UPI_INTENT",
"timestamp": 1708797965588,
"amount": 200,
"payableAmount": 200,
"feeAmount": 0,
"state": "FAILED",
"errorCode": "INVALID_MPIN",
"detailedErrorCode": "ZM"
}
]
}
}
Response Parameters
Parameter Name | Data Type | Description |
merchantId | STRING | Unique Id assigned to the merchant in the PhonePe system. Assigned during merchant onboarding. |
merchantOrderId | STRING | Unique OrderId passed by the merchant while creating the order. |
orderId | STRING | PhonePe generated orderID |
state | STRING | Status of the Mandate Setup. Possible values: ● COMPLETED ● FAILED ● PENDING |
amount | LONG | Passed by the merchant in Paise |
expireAt | DateTime | Epoch Time (in milliseconds) |
errorCode | STRING | Failure reason [PRESENT ONLY IF STATE = FAILED] |
detailedErrorCode | STRING | Detailed Failure reason [PRESENT ONLY IF STATE = FAILED] |
MetaInfo | ARRAY | Metadata passed by the merchant only. |
paymentFlow | OBJECT | Detail of Subscription. |
paymentFlow.type | STRING | Type should be “SUBSCRIPTION_REDEMPTION” for redemption. |
paymentFlow.merchantSubscriptionId | STRING | Subscription ID passed by merchant |
paymentFlow.amountType | STRING | Nature of redemption amount Possible Values: ● FIXED ● VARIABLE |
paymentFlow.maxAmount | LONG | Max amount upto which redemptions will be allowed |
paymentFlow.frequency | STRING | Subscription frequency |
paymentFlow.subscriptionId | STRING | PhonePe generated Subscription Id |
paymentDetails | ARRAY | Details of the payment |
Callbacks – State Change
Subscription Cancelled
Note: Merchants should rely only on the highlighted “payload.state” parameter for the subscription status confirmation.
{
"type": "SUBSCRIPTION_CANCELLED",
"payload": {
"merchantSubscriptionId": "MS1708797962855",
"subscriptionId": "OMS2402242336054995042603",
"state": "CANCELLED",
"authWorkflowType": "TRANSACTION",
"amountType": "FIXED",
"maxAmount": 200,
"frequency": "ON_DEMAND",
"expireAt": 1737278524000,
"pauseStartDate": 1708798426196,
"pauseEndDate": 1708885799000
}
}
Subscription Revoked
Note: Merchants should rely only on the highlighted “payload.state” parameter for the subscription status confirmation.
{
"type": "SUBSCRIPTION_REVOKED",
"payload": {
"merchantSubscriptionId": "MS1708797962855",
"subscriptionId": "OMS2402242336054995042603",
"state": "REVOKED",
"authWorkflowType": "TRANSACTION",
"amountType": "FIXED",
"maxAmount": 200,
"frequency": "ON_DEMAND",
"expireAt": 1737278524000,
"pauseStartDate": 1708798426196,
"pauseEndDate": 1708885799000
}
}
Subscription Paused
Note: Merchants should rely only on the highlighted “payload.state” parameter for the subscription status confirmation.
{
"type": "SUBSCRIPTION_PAUSED",
"payload": {
"merchantSubscriptionId": "MS1708797962855",
"subscriptionId": "OMS2402242336054995042603",
"state": "PAUSED",
"authWorkflowType": "TRANSACTION",
"amountType": "FIXED",
"maxAmount": 200,
"frequency": "ON_DEMAND",
"expireAt": 1737278524000,
"pauseStartDate": 1708798426196,
"pauseEndDate": 1708885799000
}
}
Subscription Unpaused
Note: Merchants should rely only on the highlighted “payload.state” parameter for the subscription status confirmation.
{
"type": "SUBSCRIPTION_UNPAUSED",
"payload": {
"merchantSubscriptionId": "MS1708797962855",
"subscriptionId": "OMS2402242336054995042603",
"state": "ACTIVE",
"authWorkflowType": "TRANSACTION",
"amountType": "FIXED",
"maxAmount": 200,
"frequency": "ON_DEMAND",
"expireAt": 1737278524000,
"pauseStartDate": null,
"pauseEndDate": null
}
}
Response Parameters
Parameter Name | Data Type | Description |
---|---|---|
merchantSubscriptionId | String | Unique merchant subscription Id passed by the merchant while creating the subscription. |
subscriptionId | String | Phone generated subscription Id. |
state | String | Status of the subscription. Possible values: ● ACTIVE ● CANCELLED ● REVOKED ● PAUSED |
authWorkflowType | String | Type of Authorisation |
amountType | String | Type of amount Fixed and Variable |
maxAmount | String | Max Amount that can be charged |
frequency | String | Frequency type of subscription |
expireAt | DateTime | Subscription Expiry Time (in milliseconds) |
pauseStartDate | DateTime | Subscription pause start date only for Pause State or else null. (in milliseconds) |
pauseEndDate | DateTime | Subscription pause end date only for Pause state or else null. (in milliseconds) |