Partner Checklist (Standard)


Once integration is complete, Partners must share their UAT instance for end-to-end flow verification.
All issues identified during UAT must be fixed and verified by the Partner’s integration POC in the UAT environment itself.

Sign-Off Criteria:

  • All mandatory use cases must be successfully validated.
  • The integration POC will provide UAT Sign-Off only after complete verification.
  • The Partner must acknowledge the sign-off to receive Production credentials.

The following checklist ensures all required scenarios are validated during integration for smooth UAT closure:

  • The expires_at parameter in the response should be used to determine token validity.
  • Option 1:
    • Check whether the token is active or expired before every API request.
    • If active, the same token can be reused.
    • If expired, call the Authorization API to regenerate a new token and use it.
  • Option 2:
    • Set up a scheduler to regenerate a new token by calling the Authorization API 3 to 5 minutes before expiry of the existing token.

⚠️ Avoid Unnecessary Authorization Calls!


Do not call the Authorization API before every request. Always check and rely on the token expiry time.

Request

Common Parameters

  • merchantOrderId A unique merchantOrderId must be passed for every request.
  • expireAfter Order expiry in seconds. If not passed, the default value will be applied.
    • For Custom Checkout Min = 300, Max = 5184000 (in seconds)
  • amount The value must be passed in paise (multiply the amount in INR by 100).
  • udf User-defined fields should be passed in metaInfo only if required. Currently, 5 fields are supported. Use only the fields needed and remove unused fields instead of passing empty values.
  • paymentFlow.type Must be passed as PG.

ℹ️ Available UPI Apps!


Only list UPI apps that are available on the user’s device.

  • paymentFlow.paymentMode.type Set this value to UPI_INTENT
  • paymentFlow.paymentMode.targetApp
    • For Android pass the package name of the UPI app chosen by the user.
    • For iOS pass the static app name of the UPI app chosen by the user.
  • deviceContext.deviceOS Pass ANDROID or IOS based on the platform.
  • deviceContext.merchantCallBackScheme [iOS only] Pass the URL schema of the merchant app.

ℹ️ Validate VPA Before API Call!


Always validate the VPA entered by the user with the UPI Address Validate API before invoking this API. If the VPA is invalid, display an appropriate error message to the user.

  • paymentFlow.paymentMode.type Set this value to UPI_COLLECT.
  • paymentFlow.paymentMode.details.type Set this value to VPA.
  • paymentFlow.paymentMode.details.vpa Pass the customer’s VPA as entered.
  • paymentFlow.paymentMode.type → Set this value to UPI_QR.

📘 QR Code Generation Guidance!


Can use either the intentUrl or the qrData received in the response to generate a QR code image and display it on the checkout page.

📘 PCI DSS Compliance Requirement!


Must be PCI DSS compliant in order to process payments using the Custom Card Flow.

  • paymentFlow.paymentMode.type Set this value to CARD
  • cardDetails.encryptedCardNumber Pass the 16-digit card number entered by the customer. This must be RSA-4096 encrypted using the provided Public Key.
  • cardDetails.encryptionKeyId Pass the numeric Key ID associated with the provided Public Key.
  • cardDetails.expiry.month Pass the card expiry month.
  • cardDetails.expiry.year Pass the card expiry year (4 digits).
  • cardDetails.encryptedCvv Pass the 3-digit CVV entered by the customer. This must be RSA-4096 encrypted using the provided Public Key.
  • paymentFlow.merchantUrls.redirectUrl Pass the Merchant’s redirection URL. The UI control will be returned to this URL once the payment is completed by the customer.

📘 PCI DSS Compliance Requirement!


Must be PCI DSS compliant in order to process payments using the Custom Card Flow.

  • paymentFlow.paymentMode.type Set this value to TOKEN
  • tokenDetails.encryptedToken Pass the token number entered by the customer. This must be RSA-4096 encrypted using the provided Public Key.
  • tokenDetails.encryptionKeyId Pass the numeric Key ID associated with the provided Public Key.
  • tokenDetails.expiry.month Pass the expiry month of the tokenised card.
  • tokenDetails.expiry.year Pass the expiry year of the tokenised card (4 digits).
  • tokenDetails.encryptedCvv Pass the 3-digit CVV entered by the customer. This must be RSA-4096 encrypted using the provided Public Key.
  • tokenDetails.cryptogram Pass the cryptogram generated and returned by the card network or gateway during tokenisation.
  • tokenDetails.panSuffix Pass the last four digits of the original card number.
  • paymentFlow.merchantUrls.redirectUrl Pass the Merchant’s redirection URL where UI control will return once the payment is completed by the customer.

📘 Listing Supported Banks!


Should fetch the list of supported banks and their respective Bank IDs. Only these banks must be shown on the checkout page and routed to PhonePe.

  • paymentFlow.paymentMode.type Set this value to NET_BANKING
  • paymentFlow.paymentMode.bankId Pass the bankId corresponding to the bank selected by the customer.
  • paymentFlow.merchantUrls.redirectUrl Pass the Merchant’s redirection URL where UI control will return once the payment is completed by the customer.

Response

  • orderId In the Payment API response, PhonePe provides the orderId parameter which is the PhonePe-generated Order ID for that transaction. Map this orderId with the merchantOrderId passed in the request.
  • redirectUrl In the Payment API response for Card, Token, and NetBanking, the redirectUrl parameter contains the bank’s redirection URL. Redirect the customer to this URL on the browser. Ensure the URL shared by PhonePe is used exactly as received, without modification or truncation.
  • intentUrl In the Payment API response for UPI Intent or UPI QR, the intentUrl parameter contains the intent URL. Launch this URL on the UI. Ensure the URL shared by PhonePe is used exactly as received, without modification or truncation.
  • Do not perform strict deserialization of the response payload.
  • Always rely on the root-level state parameter for payment status confirmation.
  • Possible Values of state
    • COMPLETED Transaction is successful.
    • FAILED Transaction has failed.
    • PENDING Transaction is still in progress.

Handling the PENDING Scenario

If the state = PENDING, there are two possible approaches:

  • Option 1:
    • Mark the transaction as Failed on the UI and show the Payment Failure page.
    • Continue to reconcile the transaction on the server side until a terminal status (COMPLETED or FAILED) is received.
    • If the transaction is later marked as COMPLETED, initiate a Refund.
    • Note: For this approach, it is highly recommended to integrate the Refund API.
  • Option 2:
    • Mark the transaction as Pending on the UI and show the Payment Pending page.
    • Continue to reconcile the transaction on the server side until a terminal status (COMPLETED or FAILED) is received.
    • If the transaction is later marked as COMPLETED, proceed with order fulfilment.

Order Status API – Reconciliation [Mandatory]

For PENDING transactions, the Order Status API must be called at the following intervals:

  • First status check at 20–25 seconds after transaction start.
  • Then, every 3 seconds for the next 30 seconds.
  • Then, every 6 seconds for the next 60 seconds.
  • Then, every 10 seconds for the next 60 seconds.
  • Then, every 30 seconds for the next 60 seconds.
  • Finally, every 1 minute until the transaction reaches a terminal state (COMPLETED or FAILED), or until the expireAfter value (from the request) is reached.
  • Do not perform strict deserialization of the response payload.
  • Always rely on the root-level payload.state parameter for payment status confirmation.
  • Do not use the type parameter in the webhook response (this will be deprecated). Instead, use the event parameter as the webhook event identifier.
  • expireAt and timestamp parameters are provided as epoch timestamps in milliseconds.

Security Validation [Mandatory]

  • On receiving a webhook, calculate the Authorization header value using the formula: SHA256(username:password)
  • Compare the computed value with the Authorization header received in the webhook request.
  • Only if both values match, update the payment status.
  • If the values do not match, treat the webhook as fraudulent and ignore it.
  • In case of a mismatch, the Order Status API should be used to fetch the real-time transaction status.

Webhook APIs

  • Currently, Partner-level Webhook is supported (Merchant-level webhook is not supported).
  • Use the Webhook API to configure the webhook URL by providing the following:
    • Webhook URL
    • Username (Partner-defined)
    • Password (Partner-defined)
    • List of webhook events
  • Ensure that duplicate webhooks are not configured.
  • PhonePe provides APIs to List, Update, and Delete webhook configurations. Use these appropriately based on your integration needs.

📘 Refund Processing through API!


Refunds can be initiated either through the Dashboard or by using the API. The following details apply only when the refund is initiated through the API.

  • merchantRefundId Always pass a unique ID for each refund request.
  • originalMerchantOrderId Pass the merchantOrderId used in the original Payment API request for which the refund is to be processed.
  • amount Pass the refund amount in paise (multiply the rupee value by 100).
  • Once a refund is initiated, the initial state will be PENDING.
  • The updated refund status can be obtained through:
    • Webhook (async notification), and
    • Refund Status API (active polling).
  • Mandatory Both Webhook handling and Refund Status API implementation are required to ensure accurate refund reconciliation.
  • Do not perform strict deserialization of the response payload.
  • Always rely on the root-level state parameter for refund status confirmation.
  • If the state = PENDING or CONFIRMED:
    • Continue polling the Refund Status API using the merchantRefundId until a terminal state (COMPLETED or FAILED) is reached.
    • Configure a Scheduler/Cron Job as per your convenience for reconciliation.
    • Do not initiate another refund for the same transaction while the current refund is still in PENDING or CONFIRMED state.
  • If the state = COMPLETED:
    • The refund has been processed successfully.
  • If the state = FAILED:
    • The refund request has failed.
    • A new refund request must be initiated with a unique merchantRefundId.

Here’s a polished documentation-style version of your TSP Headers section with structured formatting:

Prerequisites

  • Web: Each end merchant must have a unique domain name.
    • Example:
      • Merchant A https://abc.test.com
      • Merchant B https://def.test.com
  • Android/iOS: Each end merchant must have their own Android or iOS app with a unique package name (Android) or bundle identifier (iOS).

Payment API

Common Headers

  • Authorization Token generated using Partner Credentials.
  • X-MERCHANT-ID The MID provided by PhonePe for the end merchant. This value differs for each merchant, and the correct MID must always be passed.
  • X-SOURCE → Must be set to API.
  • X-SOURCE-PLATFORM The TSP Name provided by the Integration Team.
    • Note: For Production, the Integration Team will share this value when Production credentials are released.
  • X-SOURCE-CHANNEL Dynamic value based on the platform where the transaction is initiated. Possible values: web, android, ios.
  • X-MERCHANT-IP The IP address of the end merchant system from where the request is initiated.

Additional Headers for Web

  • X-BROWSER-FINGERPRINT Dynamically generate the browser fingerprint from the customer’s browser.
  • USER-AGENT Dynamically capture the User Agent of the customer’s browser.
  • X-MERCHANT-DOMAIN Dynamically capture the merchant’s domain from where the transaction is initiated.

Additional Headers for Android

  • X-SOURCE-CHANNEL-VERSION Android OS version.
  • X-MERCHANT-APP-ID Package name of the merchant’s Android app.

Additional Headers for iOS

  • X-SOURCE-CHANNEL-VERSION iOS version.
  • X-MERCHANT-APP-ID Bundle ID of the merchant’s iOS app.

Other APIs

  • For Order Status, Refund, and Refund Status APIs Both Authorization and X-MERCHANT-ID headers are mandatory.
  • For Webhook APIs Only Authorization header is required. The X-MERCHANT-ID header is not needed.
Is this article helpful?