Token
This flow enables card-on-file/tokenized card payments. Encryption and PCI-DSS compliance are mandatory.
⚠️ Security Requirement!
- You must be PCI DSS certified to integrate with the Custom Card Flow.
- Card Number and CVV must be encrypted using RSA 4096 with padding method RSA/ECB/PKCS1Padding.
- The encryptionKey and encryptionKeyId will be provided at the MID level.
- If operating with multiple MIDs, the encryption credentials will differ for each MID. Avoid hardcoding these values.
Environment
| Environment | HTTP Method | API |
| Sandbox | POST | https://api-preprod.phonepe.com/apis/pg-sandbox/payments/v2/pay |
| Production | POST | https://api.phonepe.com/apis/pg/payments/v2/pay |
⚠️ Setup Required to Avoid Errors!
Before initiating a payment, install the PhonePe Test App and configure the payment template. Skipping this step may result in HTTP 500 errors.
Request
| Header Name | Header Value | Description |
| Content-Type | application/json | |
Authorization | O-Bearer <access_token> | Pass access_token received in Authorization call |
⚠️ For Partner Integrations!
It is mandatory to include the X-MERCHANT-ID header with the MerchantID of the end merchant.
| Parameter Name | Data Type | Mandatory | Description | Constraints |
merchantUserId | String | No | ||
merchantOrderId | String | Yes | Unique merchant order id generated by merchant. | Max Length = 63 charactersNo Special characters allowed except underscore “_” and hyphen “-“ |
amount | Long | Yes | Order amount in paisa. | Min Value = 100 (In paise) |
expireAfter | Long | No | Order expiry in seconds. If not passed default value will be used. | Min Value = 300, Max Value = 5184000 Default Value (in Secs): UPI QR: 480 UPI Intent : 600 UPI Collect: 480 Card : 720 NetBanking : 480 |
metaInfo | Object | No | Merchant defined meta info to store additional information.same data will be returned in status and callback response. | |
deviceContext.deviceOS | String | Yes | device OS required only in case of UPI_INTENT | Values Allowed = [IOS, ANDROID] |
deviceContext.merchantCallBackScheme | String | Yes | Merchant Callback Scheme. Required only in case targetApp = PHONEPE and deviceContext.deviceOS = IOS | |
paymentFlow | Object | Yes | Additional details required by this flow. | |
paymentMode.type | String | Yes | Type of payment mode | Values Allowed: • UPI_INTENT • UPI_COLLECT • UPI_QR • NET_BANKING • TOKEN • CARD |
authMode | String | Yes | Defaults to 3DS | |
merchantUrls.redirectUrl | String | Yes | Url where user will be redirected after completing the payment. Mandatory only for [NET_BANKING, TOKEN, CARD] Payment Mode. | Valid Http url. |
The metaInfo object contains additional parameters, which are explained in the table below.
| Parameter Name | Data Type | Description | Mandatory (Yes/No) | Constraints |
metaInfo.udf1-15 | String | Optional details you can add for more information | No | • Maximum length for Udf1-10 = 256 characters • Maximum length for Udf11-15 = 50 characters |
⚠️ Do Not Rename metainfo Parameters!
It is mandatory to keep the parameter names udf1, udf2, etc., exactly as they are in the metainfo block. Renaming these key values will result in a production error.
The tokenDetails object contains additional parameters, which are explained in the table below.
| Parameter Name | Data Type | Mandatory | Description | Constraints |
tokenDetails.encryptionKeyId | Integer | Yes | KeyId of key which merchant uses to encrypt card number/Token & CVV. | |
tokenDetails.encryptedToken | String | Yes | Encrypted TOKEN number which merchant passes to process card transaction. Encryption Method: RSA 4096 with Padding: RSA/ECB/PKCS1Padding | |
tokenDetails.encryptedCvv | String | Yes | Encrypted CVV of the card with which payment is being initiated. Encryption Method: RSA 4096 with Padding: RSA/ECB/PKCS1Padding | |
tokenDetails.cryptogram | String | Yes | The cryptogram fetched from the gateway where the card was tokenized. | |
tokenDetails.panSuffix | String | Yes | Last four digits of cardNumber. | |
tokenDetails.cardHolderName | String | No | Card Holder Name. | |
tokenDetails.expiry.month | String | Yes | Token expiry month. | |
tokenDetails.expiry.year | String | Yes | Token expiry year. |
{
"merchantOrderId": "TX123456",
"amount": 1000,
"expireAfter": 1200,
"metaInfo": {
"udf1": "<additional-information-1>",
"udf2": "<additional-information-2>",
"udf3": "<additional-information-3>",
"udf4": "<additional-information-4>",
"udf5": "<additional-information-5>",
"udf6": "<additional-information-6>",
"udf7": "<additional-information-7>",
"udf8": "<additional-information-8>",
"udf9": "<additional-information-9>",
"udf10": "<additional-information-10>",
"udf11": "<additional-information-11>",
"udf12": "<additional-information-12>",
"udf13": "<additional-information-13>",
"udf14": "<additional-information-14>",
"udf15": "<additional-information-15>"
},
"paymentFlow": {
"type": "PG",
"paymentMode" : {
"type" : "TOKEN",
"authMode": "3DS",
"tokenDetails": {
"encryptedToken": "<encryptedToken>",
"encryptionKeyId": 122,
"expiry": {
"month": "12",
"year": "2029"
},
"panSuffix": "<panSuffix>",
"cardHolderName": "Dummy Name",
"cryptogram": "<cryptogram>",
"encryptedCvv": "<encryptedCvv>"
},
"merchantUserId": "dummyUser"
},
"merchantUrls": {
"redirectUrl": "<redirectUrl>"
}
}
}Response
{
"orderId": "OMO123456789",
"state": "PENDING",
"expireAt": 1703756259307,
"redirectUrl": ""
}| Field Name | Data Type | Description |
orderId | String | PG generated internal order id. |
state | String | State of the order created, Expected value is CREATED. |
expiryAt | Long | Order expiry date in epoch (in milliseconds). |
redirectUrl | String | Url where merchant is supposed to redirect user to complete payment. |