The PhonePe Docs Developer Hub

Welcome to the PhonePe Docs developer hub. You'll find comprehensive guides and documentation to help you start working with PhonePe Docs as quickly as possible, as well as support if you get stuck. Let's jump right in!

Get Started

Primary APIs

 


This section details the APIs you need to work with to accept payments on your web integration using PhonePe and for handling operational issues related to payments (eg: display balance, user details).

Accept Payments v3

Debit is a UI based workflow to allow for Login/Registration to accept payments.

 
posthttps://mercury-uat.phonepe.com/v3/debit
curl --request POST \
  --url https://mercury-uat.phonepe.com/v3/debit \
  --header 'content-type: application/json' \
  --header 'x-verify: X-VERIFY'
var request = require("request");

var options = { method: 'POST',
  url: 'https://mercury-uat.phonepe.com/v3/debit',
  headers:
   { 'x-verify': 'X-VERIFY',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/debit")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = 'X-VERIFY'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://mercury-uat.phonepe.com/v3/debit");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "X-VERIFY");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/debit"

headers = {
    'content-type': "application/json",
    'x-verify': "X-VERIFY"
    }

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

Found. Redirecting to /app?token=YTdhMDlmYTg5YWZkNWE5ZDcyYzVhM2FhMmRjNWU0OThhZTFkOTc1MGZiYzBmMmY5ZGU4ODc0Njk2ZWM2Njg2NmFmZGFlMzAxOWIzNTYyOWVkOWJmOGY0NDhjMDlmZDllMzIwZGRkMGEyZjIxMWI0M2E2ZmZhNjRkNDEwNjQ5MTI1ODc5OTllMTI5MGIwNTJmM2M5ZWUxMzA=
{
  "success": false,
  "code": "INVALID_TRANSACTION_ID",
  "message": "The transaction id you have entered seems to be invalid.",
  "data": {}
}

Body Params

request
string
required

base64 encoded payload

Headers

Content-Type
string
required
X-VERIFY
string
required

SHA256(base64 encoded payload + "/v3/debit" + salt key) + ### + salt index

X-REDIRECT-URL
string

Dynamic redirect URI for UI callback

X-REDIRECT-MODE
string

HTTP mode to be used for UI callback. Default Values are REDIRECT/POST.

X-CALLBACK-URL
string

Dynamic callback URI for server to server callback

X-CALL-MODE
string

HTTP mode to be used for server to server callback. Default Values are POST/PUT

 

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256(base64 encoded payload + "/v3/debit" +
salt key) + ### + salt index

X-REDIRECT-URL

Dynamic redirect URI for UI callback

X-REDIRECT-MODE

HTTP mode to be used for UI callback

X-CALLBACK-URL

Dynamic callback URI for server to server callback

X-CALL-MODE

HTTP mode to be used for server to server callback

X-PROVIDER-ID

Used for the cases where the merchant has multiple merchant IDs

{  
   "merchantId":"M2306160483220675579140",
   "transactionId":"TX123456789",
   "merchantUserId":"U123456789",
   "amount":100,
   "merchantOrderId":"OD1234",
   "mobileNumber":"9xxxxxxxxx",
   "message":"payment for order placed OD1234",
   "subMerchant":"DemoMerchant",
   "email":"amit***75@gmail.com",
   "shortName":"Amit"
}
{
  "request": "eyAgCiAgICJtZXJjaGFudElkIjoiTTIzMDYxNjA0ODMyMjA2NzU1NzkxNDAiLAogICAidHJhbnNhY3Rpb25JZCI6IlRYMTIzNDU2Nzg5IiwKICAgIm1lcmNoYW50VXNlcklkIjoiVTEyMzQ1Njc4OSIsCiAgICJhbW91bnQiOjEwMCwKICAgIm1lcmNoYW50T3JkZXJJZCI6Ik9EMTIzNCIsCiAgICJtb2JpbGVOdW1iZXIiOiI5eHh4eHh4eHh4IiwKICAgIm1lc3NhZ2UiOiJwYXltZW50IGZvciBvcmRlciBwbGFjZWQgT0QxMjM0IiwKICAgInN1Yk1lcmNoYW50IjoiRGVtb01lcmNoYW50IiwKICAgImVtYWlsIjoiYW1pdCoqKjc1QGdtYWlsLmNvbSIsCiAgICJzaG9ydE5hbWUiOiJBbWl0Igp9"
}

Request Parameters

Parameter Name
Type
Description
Mandatory

merchantId

STRING

Unique MerchantID assigned to the merchant by PhonePe

Yes

transactionId

STRING

Unique TransactionID generated by the merchant to track request to PhonePe
transactionId length should be less than 38 characters.

Yes

merchantUserId

STRING

Unique UserID generated by merchant. This is used to pre-login users authenticated on PhonePe. Un-authenticated users are redirected to PhonePe login page. Conversions are higher when this is provided. Avoid passing email/mobile number.
Skip this for guest users.
Note:
Don't pass this if you are passing userAuthToken.

Yes

userAuthToken

STRING

Unique userAuthTokengiven to merchant in OTP flow. This is used to pre-login users authenticated on PhonePe. If not passed users will be redirected to PhonePe login page.
Note : Used only for OTP linking flow.


amount

LONG

Transaction amount in Paise

Yes

merchantOrderId

STRING

OrderID generated by the merchant
merchantOrderId length should be less than 48 characters.

No

subMerchant

STRING

.Tag to categorize merchant transaction.
Skip this field if you don't have multiple merchants tagged under one merchant id

No

mobileNumber

STRING

Mobile number of the user

No

message

STRING

Short message. This message is displayed to the user on completion of payment.

No

email

STRING

Email address of the user

No

shortName

STRING

User's name pre-filled for registration purpose.

No

Response Parameters

Parameter Name
Type
Description

success

Boolean

Success status of the request

code

Enum

See list of response codes below

shortName

String

Short message about code

Regular Debit Response Codes

Code
Description

INVALID_TRANSACTION_ID

Duplicate TransactionID

INVALID_USER_AUTH_TOKEN

The userAuthToken provided is either invalid or not mapped to merchant.

BAD_REQUEST

Invalid request payload

AUTHORIZATION_FAILED

Incorrect X-VERIFY header

INTERNAL_SERVER_ERROR

Something went wrong

1.Make sure that 'follow redirection' is disabled while calling this API.
2.This location endpoint should be appended to host to get the complete redirection URL.
3.It's recommended to have the server to server call back using x-callback-url header.

Once the transaction is complete, user will be redirected back to the merchant.

Accept Payments v4

 
posthttps://mercury-uat.phonepe.com/v4/debit/
curl --request POST \
  --url https://mercury-uat.phonepe.com/v4/debit/ \
  --header 'content-type: application/json' \
  --header 'x-verify: X-VERIFY'
var request = require("request");

var options = { method: 'POST',
  url: 'https://mercury-uat.phonepe.com/v4/debit/',
  headers:
   { 'x-verify': 'X-VERIFY',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v4/debit/")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = 'X-VERIFY'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://mercury-uat.phonepe.com/v4/debit/");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "X-VERIFY");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v4/debit/"

headers = {
    'content-type': "application/json",
    'x-verify': "X-VERIFY"
    }

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "code": "SUCCESS",
  "message": "Your request has been successfully completed.",
  "data": {
  "redirectType": "WEB",
  "redirectURL": "https://mercury.phonepe.com/transaction?token=fkjsdfka9248jfksjdfkilfjksdk"
    }
}
{
  "success": false,
  "code": "INVALID_TRANSACTION_ID",
  "message": "The transaction id you have entered seems to be invalid.",
  "data": {}
}

Body Params

request
string
required

base64 encoded payload

Headers

Content-Type
string
required
X-VERIFY
string
required

SHA256(base64 encoded payload + "/v4/debit" + salt key) + ### + salt index

X-REDIRECT-URL
string

Dynamic redirect URI for UI callback

X-REDIRECT-MODE
string

HTTP mode to be used for UI callback. Default Values are REDIRECT/POST.

X-CALLBACK-URL
string

Dynamic callback URI for server to server callback

X-CALL-MODE
string

HTTP mode to be used for server to server callback. Default Values are POST/PUT

 

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256(base64 encoded payload + "/v4/debit" +
salt key) + ### + salt index

X-REDIRECT-URL

Dynamic redirect URI for UI callback

X-REDIRECT-MODE

HTTP mode to be used for UI callback

X-CALLBACK-URL

Dynamic callback URI for server to server callback

X-CALL-MODE

HTTP mode to be used for server to server callback

X-PROVIDER-ID

Used for the cases where the merchant has multiple merchant IDs

{  
   "merchantId":"M2306160483220675579140",
   "transactionId":"TX123456789",
   "merchantUserId":"U123456789",
   "amount":100,
   "merchantOrderId":"OD1234",
   "mobileNumber":"9xxxxxxxxx",
   "message":"payment for order placed OD1234",
   "subMerchant":"DemoMerchant",
   "email":"amit***75@gmail.com",
   "shortName":"Amit"
}
{
  "request": "eyAgCiAgICJtZXJjaGFudElkIjoiTTIzMDYxNjA0ODMyMjA2NzU1NzkxNDAiLAogICAidHJhbnNhY3Rpb25JZCI6IlRYMTIzNDU2Nzg5IiwKICAgIm1lcmNoYW50VXNlcklkIjoiVTEyMzQ1Njc4OSIsCiAgICJhbW91bnQiOjEwMCwKICAgIm1lcmNoYW50T3JkZXJJZCI6Ik9EMTIzNCIsCiAgICJtb2JpbGVOdW1iZXIiOiI5eHh4eHh4eHh4IiwKICAgIm1lc3NhZ2UiOiJwYXltZW50IGZvciBvcmRlciBwbGFjZWQgT0QxMjM0IiwKICAgInN1Yk1lcmNoYW50IjoiRGVtb01lcmNoYW50IiwKICAgImVtYWlsIjoiYW1pdCoqKjc1QGdtYWlsLmNvbSIsCiAgICJzaG9ydE5hbWUiOiJBbWl0Igp9"
}

Request Parameters

Parameter Name
Type
Description
Mandatory

merchantId

STRING

Unique MerchantID assigned to the merchant by PhonePe

Yes

transactionId

STRING

Unique TransactionID generated by the merchant to track request to PhonePe
transactionId length should be less than 38 characters.

Yes

merchantUserId

STRING

Unique UserID generated by merchant. This is used to pre-login users authenticated on PhonePe. Un-authenticated users are redirected to PhonePe login page. Conversions are higher when this is provided. Avoid passing email/mobile number.
Skip this for guest users.
Note:
Don't pass this if you are passing userAuthToken.

Yes

userAuthToken

STRING

Unique userAuthTokengiven to merchant in OTP flow. This is used to pre-login users authenticated on PhonePe. If not passed users will be redirected to PhonePe login page.
Note : Used only for OTP linking flow.


amount

LONG

Transaction amount in Paise

Yes

merchantOrderId

STRING

OrderID generated by the merchant
merchantOrderId length should be less than 48 characters.

No

subMerchant

STRING

.Tag to categorize merchant transaction.
Skip this field if you don't have multiple merchants tagged under one merchant id

No

mobileNumber

STRING

Mobile number of the user

No

message

STRING

Short message. This message is displayed to the user on completion of payment.

No

email

STRING

Email address of the user

No

shortName

STRING

User's name pre-filled for registration purpose.

No

Response Parameters

Parameter Name
Type
Description

success

Boolean

Success status of the request

code

Enum

See list of response codes below

shortName

String

Short message about code

Regular Debit Response Codes

Code
Description

INVALID_TRANSACTION_ID

Duplicate TransactionID

INVALID_USER_AUTH_TOKEN

The userAuthToken provided is either invalid or not mapped to merchant.

BAD_REQUEST

Invalid request payload

AUTHORIZATION_FAILED

Incorrect X-VERIFY header

INTERNAL_SERVER_ERROR

Something went wrong

1.Make sure that 'follow redirection' is disabled while calling this API.
2.This location endpoint should be appended to host to get the complete redirection URL.
3.It's recommended to have the server to server call back using x-callback-url header.

Once the transaction is complete, user will be redirected back to the merchant.

UI Callback

 


  • The Callback is sent to a URL that is passed in X-REDIRECT-URL header along with request.
  • The value of X-REDIRECT-MODE header should be POST to get UI callback.

Form Post Response Payload

Parameter Name
Description

code
Enum

See list of codes.

merchantId
String

merchantId

transactionId
String

Unique Transaction ID

amount
Long

Transaction amount in paise

providerReferenceId
String

PhonePe ReferenceId.

param1
String

Optional Parameter, to be used later

param2
String

Optional Parameter, to be used later

param3
String

Optional Parameter, to be used later

param4
String

Optional Parameter, to be used later

param5
String

Optional Parameter, to be used later

param6
String

Optional Parameter, to be used later

param7
String

Optional Parameter, to be used later

param8
String

Optional Parameter, to be used later

param9
String

Optional Parameter, to be used later

param10
String

Optional Parameter, to be used later

param11
String

Optional Parameter, to be used later

param12
String

Optional Parameter, to be used later

param13
String

Optional Parameter, to be used later

param14
String

Optional Parameter, to be used later

param15
String

Optional Parameter, to be used later

param16
String

Optional Parameter, to be used later

param17
String

Optional Parameter, to be used later

param18
String

Optional Parameter, to be used later

param19
String

Optional Parameter, to be used later

param20
String

Optional Parameter, to be used later

checksum
String

The checksum for this entire request

How is checksum computed for a Form POST?

  • The server itself will generate the checksum, by doing a SHA256(code + merchantId + transactionId + amount + providerReferenceId + param1 + param2 +...... + param20 + saltKey).
  • The salt we would use will be appended with ### to the checksum value in the checksum attribute. Merchants upon receiving this payload, will look at the salt_index in the checksum attribute after ### delimiter and use the appropriate salt_index to be able to calculate checksum at their end for the said payload. If it doesn't match, then they will need to abort the request.
  • Salts are already pre-shared with the merchant when they are onboarded.
  • If value of any parameter is null, it will not be included in calculation of checksum.

Transaction Status Response Codes

Code
Description

TRANSACTION_NOT_FOUND

Payment not initiated inside PhonePe

BAD_REQUEST

Invalid request

AUTHORIZATION_FAILED

X-VERIFY header is incorrect

INTERNAL_SERVER_ERROR

Something went wrong. Merchant needs to call Check Transaction Status to verify the transaction status.

PAYMENT_SUCCESS

Payment is successful

PAYMENT_ERROR

Payment failed

PAYMENT_PENDING

Payment is pending. It does not indicate failed payment. Merchant needs to call Check Transaction Status to verify the transaction status.

PAYMENT_DECLINED

Payment declined by user

PAYMENT_CANCELLED

Payment cancelled by the merchant using Cancel API

Server to Server Callback

 
  • Server to server callbacks are initiated from PhonePe server to the url provided by merchant when payment reaches to any terminal state (SUCESS or FAIL)
  • There are two ways to enable server to server callbacks.
    1.Either Register your static callback url with PhonePe. This is a one time process.
    2.Or, Send the callback url along with each payment request.

The URL is specified in header X-CALLBACK-URL
HTTP mode for callback is specified in header X-CALL-MODE

If different callback url is present at each location, then preference will be given to second method.

Payload

The payload that is going to be sent to the merchant on the specified callback url will have a base64 encoded json.

Upon base64 decoding the response, you should get a json with format similar to the response returned by transaction status API.

This is the best case callback that would be sent from PhonePe server to the merchants' server. In the event of a callback failure, the onus is on the merchants to use the transaction status API and take the transaction to closure.

Callback headers

Following are the response headers sent with a callback.

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256(response + salt key) + ### + salt index

Response Parameters

Parameter Name
Description

success
BOOLEAN

true/ false

code
ENUM

This parameter is used to decide if payment is success or failed (see list of codes below)

message
STRING

Descriptive message

transactionId
STRING

transactionId (if this is static QR then this will be generated by PhonePe)

merchantId

STRING

merchantId

amount
LONG

Amount in paisa

providerReferenceId
STRING

PhonePe transactionId

paymentState
STRING

COMPLETED/ FAILED

payResponseCode
STRING

More granular error codes for failure.
(Optional parameter to be sent in response)

*paymentModes

  • List

Please see below for schema
(Optional parameter to be sent in response)

transactionContext
Object

Please see below for schema
(Optional parameter to be sent in response)

Server to Server Callback Response Codes

Code
Description

PAYMENT_SUCCESS

Payment is successful for QR scan

PAYMENT_ERROR

Payment failed for QR scan

PAYMENT_DECLINED

Payment declined by customer

PAYMENT_CANCELLED

Payment cancelled by merchant

Payment Modes (Optional parameter to be sent in response)

Parameter Name
Description

mode

ACCOUNT/ WALLET/
EXTERNAL_WALLET/ DEBIT_CARD/
CREDIT_CARD/ EXTERNAL_VPA/
EGV/ NET_BANKING

amount

Amount in paisa

utr

UTR for UPI payments.

Transaction Context (Optional parameter to be sent in response)

Parameter Name
Description

qrCodeId

VPA

storeId

Store Id

terminalId

Terminal Id

curl -X POST \
  https://api.merchant.com/response/phonepe \
  -H 'content-type: application/json' \
  -H 'x-verify: 2abaa82a4810c57dcd6aa52680dd772173b1e40770afe028131f31ddbe5487a8###1' \
  -d '{
	"response":"eyJzdWNjZXNzIjp0cnVlLCJjb2RlIjoiUEFZTUVOVF9TVUNDRVNTIiwibWVzc2FnZSI6IllvdXIgcGF5bWVudCBpcyBzdWNjZXNzZnVsLiIsImRhdGEiOnsidHJhbnNhY3Rpb25JZCI6IlRYMzIzMjE4NDk2NDQyMzQiLCJtZXJjaGFudElkIjoiTTIzMDYxNjA0ODMyMjA2NzU1NzkxNDAiLCJwcm92aWRlclJlZmVyZW5jZUlkIjoiUDE4MDYxNTEzMjMwOTM5MDA1NTQ5NTciLCJhbW91bnQiOjEwMDAsInBheW1lbnRTdGF0ZSI6IkNPTVBMRVRFRCIsInBheVJlc3BvbnNlQ29kZSI6IlNVQ0NFU1MiLCJwYXltZW50TW9kZXMiOlt7Im1vZGUiOiJBQ0NPVU5UIiwiYW1vdW50IjoxMDAwLCJ1dHIiOiI4MTY2MjY1MjE2MTYifV0sInRyYW5zYWN0aW9uQ29udGV4dCI6e319fQ=="
}'
{
  "response": "eyJzdWNjZXNzIjp0cnVlLCJjb2RlIjoiUEFZTUVOVF9TVUNDRVNTIiwibWVzc2FnZSI6IllvdXIgcGF5bWVudCBpcyBzdWNjZXNzZnVsLiIsImRhdGEiOnsidHJhbnNhY3Rpb25JZCI6IlRYMzIzMjE4NDk2NDQyMzQiLCJtZXJjaGFudElkIjoiTTIzMDYxNjA0ODMyMjA2NzU1NzkxNDAiLCJwcm92aWRlclJlZmVyZW5jZUlkIjoiUDE4MDYxNTEzMjMwOTM5MDA1NTQ5NTciLCJhbW91bnQiOjEwMDAsInBheW1lbnRTdGF0ZSI6IkNPTVBMRVRFRCIsInBheVJlc3BvbnNlQ29kZSI6IlNVQ0NFU1MiLCJwYXltZW50TW9kZXMiOlt7Im1vZGUiOiJBQ0NPVU5UIiwiYW1vdW50IjoxMDAwLCJ1dHIiOiI4MTY2MjY1MjE2MTYifV0sInRyYW5zYWN0aW9uQ29udGV4dCI6e319fQ=="
}
{  
   "success":true,
   "code":"PAYMENT_SUCCESS",
   "message":"Your payment is successful.",
   "data":{  
      "transactionId":"TX32321849644234",
      "merchantId":"M2306160483220675579140",
      "providerReferenceId":"P1806151323093900554957",
      "amount":1000,
      "paymentState":"COMPLETED",
      "payResponseCode":"SUCCESS",
      "paymentModes":[  
         {  
            "mode":"ACCOUNT",
            "amount":1000,
            "utr":"816626521616"
         }
      ],
      "transactionContext":{  

      }
   }
}
  1. Success/Failure of transaction should be dependent on the code in response parameters
  2. Cross-check the amount and checksum which has been passed in forward payment path(Accept payment API) and in the response of Server to Server callback.

Check Transaction Status

This API is used to check the status of the transaction using transaction id.

 
gethttps://mercury-uat.phonepe.com/v3/transaction/merchantId/transactionId/status
curl --request GET \
  --url https://mercury-uat.phonepe.com/v3/transaction/M2306160483220675579140/1511522079/status \
  --header 'content-type: application/json' \
  --header 'x-verify: 6ab24e24ae92646c82e0450f029478117d8a1a0a00390e266ea1178a0c68e419###1'
var request = require("request");

var options = { method: 'GET',
  url:
   'https://mercury-uat.phonepe.com/v3/transaction/M2306160483220675579140/1511522079/status',
  headers:
   { 'x-verify':
      '6ab24e24ae92646c82e0450f029478117d8a1a0a00390e266ea1178a0c68e419###1',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/transaction/M2306160483220675579140/1511522079/status")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = '6ab24e24ae92646c82e0450f029478117d8a1a0a00390e266ea1178a0c68e419###1'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://mercury-uat.phonepe.com/v3/transaction/M2306160483220675579140/1511522079/status");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "6ab24e24ae92646c82e0450f029478117d8a1a0a00390e266ea1178a0c68e419###1");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/transaction/M2306160483220675579140/1511522079/status"

headers = {
    'content-type': "application/json",
    'x-verify': "6ab24e24ae92646c82e0450f029478117d8a1a0a00390e266ea1178a0c68e419###1"
    }

response = requests.request("GET", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "success": true,/* Rely on success flag and
   code parameter as PAYMENT_SUCCESS for 
   successful transaction */
  
  "code": "PAYMENT_SUCCESS",
  "message": "Your payment is successful.",
  "data": {
    "transactionId": "TX123456789",
    "merchantId": "U123456789",
    "amount": 100,
    "providerReferenceId": "PPXXXXXX",
    "payResponseCode": "SUCCESS",
    "paymentState": "COMPLETED"/* This is an
     informative field. For making decisions
     rely on 'code' field */
  }
}
{
  "success": false,
  "code": "TRANSACTION_NOT_FOUND",
  "message": "No Transaction found with the given details.",
  "data": {}
}

Path Params

merchantId
string
required

Unique Merchant ID assigned to the merchant by PhonePe

transactionId
string
required

Merchant transaction id for which status is to be fetched

Headers

Content-Type
string
required
X-VERIFY
string
required

SHA256("/v3/transaction/{merchantId}/{transactionId}/status" + saltKey) + "###" + saltIndex

 

It is mandatory for the merchant to check the status of a transaction post callback from Accept Payments or Refund workflows.

  • Once customer is redirected back to merchant website, it is recommended to make a transaction status check with PhonePe backend systems to know the actual status of the payment and, then accordingly process the result.
  • The payment status can be Success, Failed or Pending. When Pending, merchants should retry until the status changes to Success or Failed.

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256("/v3/transaction/{merchantId}/{transactionId}/status" +
saltKey) + "###" + saltIndex

Path Parameters

Parameter Name
Type
Description
Mandatory

merchantId

STRING

Unique Merchant ID assigned to the merchant by PhonePe

Yes

transactionId

STRING

Merchant transactionID for which status is to be fetched

Yes

Response Parameters

Parameter Name
Type
Description

success

BOOLEAN

A boolean to indicate the success/failure of the request.

code

ENUM

Please see the list of Transaction Status Response Codes below. You should base your decision on this parameter.

message

STRING

Short message about status of transaction

transactionId

STRING

Unique Transaction ID generated by the merchant to track this request to PhonePe

merchantId

STRING

Unique Merchant ID assigned to the merchant by PhonePe

amount

LONG

Transaction amount in paise

providerReferenceId

STRING

PhonePe transaction Id

paymentState

STRING

Please ignore this. Use "code" parameter to get latest status of transaction.

payResponseCode

STRING

PhonePe internal status code. Please note this is a string value and new codes are likely to be added in the future. (Please don't do the marshalling/unmarshalling into an enum for this at your side). This is an informative value.

Transaction Status Response Codes

Code
Description

TRANSACTION_NOT_FOUND

Payment not initiated inside PhonePe

BAD_REQUEST

Invalid request

AUTHORIZATION_FAILED

X-VERIFY header is incorrect

INTERNAL_SERVER_ERROR

Something went wrong. Merchant needs to call Check Transaction Status to verify the transaction status.

PAYMENT_SUCCESS

Payment is successful or In case of refund - Refund is successful.

PAYMENT_ERROR

Payment failed

PAYMENT_PENDING

Payment is pending. It does not indicate failed payment. Merchant needs to call Check Transaction Status to verify the transaction status.

PAYMENT_DECLINED

Payment declined by user

PAYMENT_CANCELLED

Payment cancelled by the merchant using Cancel API

Cross-check the amount which has been passed in forward payment path(Accept payment API) and in the response of Check Transaction Status API.

Refund

API flow to refund against a payment transaction made through PhonePe. A full or partial refund is possible against a transaction.

 
posthttps://mercury-uat.phonepe.com/v3/credit/backToSource
curl --request POST \
  --url https://mercury-uat.phonepe.com/v3/credit/backToSource \
  --header 'content-type: application/json' \
  --header 'x-verify: X-VERIFY'
var request = require("request");

var options = { method: 'POST',
  url: 'https://mercury-uat.phonepe.com/v3/credit/backToSource',
  headers:
   { 'x-verify': 'X-VERIFY',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/credit/backToSource")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = 'X-VERIFY'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://mercury-uat.phonepe.com/v3/credit/backToSource");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "X-VERIFY");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/credit/backToSource"

headers = {
    'content-type': "application/json",
    'x-verify': "X-VERIFY"
    }

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
   "success": true,
   "code": "PAYMENT_SUCCESS",
   "message": "Your payment is successful.",
   "data": {
       "transactionId": "TX123456789",
       "merchantId": "DemoMerchant",
       "amount": 100,
       "status": "SUCCESS",
       "mobileNumber": "9xxxxxxxxxx",
       "providerReferenceId": "PPXXXXX",
       "payResponseCode": "SUCCESS"
   }
}
{
  "success": false,
  "code": "INVALID_TRANSACTION_ID",
  "message": "The transaction id you have entered seems to be invalid.",
  "data": {}
}

Body Params

request
string
required

base64 encoded payload

Headers

Content-type
string
required
X-VERIFY
string
required

SHA256(base64 encoded payload + "/v3/credit/backToSource" + salt key) + ### + salt index

 

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256(base64 encoded payload + "/v3/credit/backToSource" + salt key) + ### + salt index

Request Parameters

Parameter Name
Type
Description
Mandatory

merchantId

STRING

Unique Merchant ID assigned to the merchant by PhonePe

Yes

transactionId

STRING

Unique Transaction ID generated by the merchant to track this request to PhonePe.
This should be different from transaction ID of debit transaction.

Yes

originalTransactionId

STRING

Merchant transaction Id of forward transaction which needs to be reversed.

Yes

providerReferenceId

STRING

PhonePe transaction id of the original forward payment.
Note : use only one of originalTransactionId, providerReferenceId only

Yes

amount

LONG

Reversal amount in paise. Upto a max of amount of original payment transaction.

Yes

merchantOrderId

STRING

Order ID for the merchant transaction

Yes

subMerchant

STRING

Tag to categorize merchant transaction

No

message

STRING

Short message

Yes

Response Parameters

Parameter Name
Type
Description

success

BOOLEAN

Success status of the request

code

ENUM

See list of response codes below

message

STRING

Short message about code

transactionId

STRING

Unique Transaction ID generated by the merchant to track this request to PhonePe

merchantId

STRING

Unique Merchant ID assigned to the merchant by PhonePe

amount

LONG

Transaction amount in paise

status

STRING

Status of the request

mobileNumber

STRING

Mobile number of the user

providerReferenceId

STRING

PhonePe payment transaction id against which the reversal is to be done

payResponseCode

STRING

PhonePe internal status code

Refund API Response Codes

Code
Description

BAD_REQUEST

Invalid request

AUTHORIZATION_FAILED

X-VERIFY header is incorrect

TRANSACTION_NOT_FOUND

Original transaction not found

INTERNAL_SERVER_ERROR

Something went wrong. Refund might get initiated (need to check status with check transaction status API before retrying the refund)

PAYMENT_SUCCESS

Payment is successful

PAYMENT_ERROR

Payment failed

PAYMENT_PENDING

Payment is pending. It does not indicate failed payment. Refund might get initiated (need to check status with check transaction status API before retrying the refund)

TIMED_OUT

Refund timed out. Refund might get initiated (need to check status with check transaction status API before retrying the refund)

DUPLICATE_TXN_REQUEST

If the transaction id is used already for refund request.

EXCESS_REFUND_AMOUNT

If the amount requested for refund is more than forward payment or If refund is already done

WALLLET_NOT_ACTIVATED

If the user has disabled the wallet. Contact user to know the source for refund.

{
    "merchantId": "DemoMerchant",
    "transactionId": "TX123456789",
    "providerReferenceId": "PPXXXXX",
    "amount": 100,
    "merchantOrderId": "OD1234",
    "subMerchant": "DemoMerchant",
    "message": "refund for cancelled order"
}
{
  "request": "eyJtZXJjaGFudE9yZGVySWQiOiAiT0QxMjM0IiwgInN1Yk1lcmNoYW50IjogIkRlbW9NZXJjaGFudCIsICJhbW91bnQiOiAxMDAsICJtZXNzYWdlIjogInJlZnVuZCBmb3IgY2FuY2VsbGVkIG9yZGVyIiwgIm1vYmlsZU51bWJlciI6ICI5eHh4eHh4eHh4IiwgInNob3J0TmFtZSI6ICJBbWl0IiwgInRyYW5zYWN0aW9uSWQiOiAiVFgxMjM0NTY3ODkiLCAibWVyY2hhbnRVc2VySWQiOiAiVTEyMzQ1Njc4OSIsICJtZXJjaGFudElkIjogIkRlbW9NZXJjaGFudCIsICJlbWFpbCI6ICJhbWl0eHh4NzVAZ21haWwuY29tIn0"
}

Other APIs

 


These APIs are optional. Based on the nature of your business, you may choose to integrate them.

  1. Link PhonePe Account(Optional for Web)
  2. Refund customers for missing forward transactions: This is used for online businesses that accept other modes of payment, such as cash. In the event of a return, the refund is triggered by the merchant to the linked PhonePe wallet.
    This is a 2-step process:
    a. Initiate Refund Transaction
    b. Process Refund Transaction

Initiate Refund - COD

 
posthttps://mercury-uat.phonepe.com/v3/credit/deferred
curl --request POST \
  --url https://mercury-uat.phonepe.com/v3/credit/deferred \
  --header 'content-type: application/json' \
  --header 'x-callback-url: https://www.demoMerchant.com/callback' \
  --header 'x-verify: X-VERIFY'
var request = require("request");

var options = { method: 'POST',
  url: 'https://mercury-uat.phonepe.com/v3/credit/deferred',
  headers:
   { 'x-callback-url':
      'https://www.demoMerchant.com/callback',
     'x-verify': 'X-VERIFY',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/credit/deferred")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = 'X-VERIFY'
request["x-callback-url"] = 'https://www.demoMerchant.com/callback'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://mercury-uat.phonepe.com/v3/credit/deferred");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "X-VERIFY");
xhr.setRequestHeader("x-callback-url", "https://www.demoMerchant.com/callback");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/credit/deferred"

headers = {
    'content-type': "application/json",
    'x-verify': "X-VERIFY",
    'x-callback-url': "https://www.demoMerchant.com/callback"
    }

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{}
  
{
  "success": false,
  "code": "INVALID_TRANSACTION_ID",
  "message": "The transaction id you have entered seems to be invalid.",
  "data": {}
}

Body Params

request
string
required

base64 encoded payload

Headers

Content-Type
string
required
X-VERIFY
string
required

SHA256(base64 encoded payload + "/v3/credit/deferred" + salt key) + ### + salt index

X-CALLBACK-URL
string
required

Dynamic callback URI for the API request

 



This API is used to refund to the customer where the payment transaction is missing in the system.
E.g. For payment made through Cash-On-Delivery, the forward payment is made through cash and not on PhonePe. The merchant can initiate a refund through Deferred Credit.

Deferred credit is a two-step process.
First, the merchant initiates the call to /credit/deferred for credit request.
Second, to fulfill the deferred request, the merchant calls Credit Deferred Fulfil

Request Headers

Header Name
Header Values

Content-Type

application/json

X-VERIFY

SHA256(base64 encoded payload + "/v3/credit/deferred" +
salt key) + ### + salt index

X-CALLBACK-URL

Dynamic callback URI for the API request

Request Parameters

Parameter Name
Type
Description
Mandatory

merchantId

String

Unique Merchant ID assigned to the merchant by PhonePe

Yes

transactionId

String

Unique Transaction ID generated by the merchant to track this request to PhonePe

Yes

merchantUserId

String

Unique ID assigned to the user by the merchant. This is used for linking the user’s PhonePe account.

Yes

amount

Long

Transaction amount in paise

Yes

merchantOrderId

String

Order ID for the merchant transaction

Yes

subMerchant

String

Tag to categorize merchant transaction

No

mobileNumber

String

Mobile number of the user

No

message

String

Short message

No

email

String

Email address of the user

No

shortName

String

User's name pre-filled for registration purpose.

No

Response Parameters

Parameter Name
Type
Description

success

Boolean

Success status of the request

code

ENUM

To see list of response codes go here.

message

String

Short message about code

{
  "merchantId": "DemoMerchant",
  "transactionId": "TX123456789",
  "merchantUserId": "U123456789",
  "amount": 100,
  "merchantOrderId": "OD1234",
  "subMerchant": "DemoMerchant",
  "mobileNumber": "9xxxxxxxxx",
  "message": "refund for cancelled order",
  "email": "amitxxx75@gmail.com",
  "shortName": "Amit"
}
{
  "request": "eyJtZXJjaGFudE9yZGVySWQiOiAiT0QxMjM0IiwgInN1Yk1lcmNoYW50IjogIkRlbW9NZXJjaGFudCIsICJhbW91bnQiOiAxMDAsICJtZXNzYWdlIjogInJlZnVuZCBmb3IgY2FuY2VsbGVkIG9yZGVyIiwgIm1vYmlsZU51bWJlciI6ICI5eHh4eHh4eHh4IiwgInNob3J0TmFtZSI6ICJBbWl0IiwgInRyYW5zYWN0aW9uSWQiOiAiVFgxMjM0NTY3ODkiLCAibWVyY2hhbnRVc2VySWQiOiAiVTEyMzQ1Njc4OSIsICJtZXJjaGFudElkIjogIkRlbW9NZXJjaGFudCIsICJlbWFpbCI6ICJhbWl0eHh4NzVAZ21haWwuY29tIn0"
}

Process Refund - COD

 
posthttps://mercury-uat.phonepe.com/v3/credit/deferred/fulfill
curl --request POST \
  --url https://mercury-uat.phonepe.com/v3/credit/deferred/fulfill \
  --header 'content-type: application/json' \
  --header 'x-verify: X-VERIFY'
var request = require("request");

var options = { method: 'POST',
  url: 'https://mercury-uat.phonepe.com/v3/credit/deferred/fulfill',
  headers:
   { 'x-verify': 'X-VERIFY',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/credit/deferred/fulfill")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = 'X-VERIFY'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://mercury-uat.phonepe.com/v3/credit/deferred/fulfill");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "X-VERIFY");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/credit/deferred/fulfill"

headers = {
    'content-type': "application/json",
    'x-verify': "X-VERIFY"
    }

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "success": true,
  "code": "PAYMENT_SUCCESS",
  "message": "Your payment is successful.",
  "data": {
      "transactionId": "TX123456789",
      "merchantId": "DemoMerchant",
      "amount": 100,
      "status": "SUCCESS",
      "merchantUserId": "U123456789",
      "mobileNumber": "9xxxxxxxxxx",
      "providerReferenceId": "PPXXXXX",
      "payResponseCode": "SUCCESS"
  }
}
{
  "success": false,
  "code": "INVALID_TRANSACTION_ID",
  "message": "The transaction id you have entered seems to be invalid.",
  "data": {}
}

Body Params

request
string
required

base64 encoded payload

Headers

Content-Type
string
required
X-VERIFY
string
required

SHA256(base64 encoded payload + "/v3/credit/deferred/fulfill" + salt key) + ### + salt index

 

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256(base64 encoded payload + "/v3/credit/deferred/fulfill" +
salt key) + ### + salt index

Request Parameters

Parameter Name
Type
Description
Mandatory

merchantId

String

Unique Merchant ID assigned to the merchant by PhonePe

Yes

transactionId

String

Transaction ID same as that of credit/deferredAPI

Yes

merchantUserId

String

Unique ID assigned to the user by the merchant. This is used for linking the user’s PhonePe account.

Yes

amount

Long

Transaction amount in paise

Yes

merchantOrderId

String

Order ID for the merchant transaction

Yes

subMerchant

String

Tag to categorize merchant transaction

No

mobileNumber

String

Mobile number of the user

No

message

String

Short message displayed on success page

No

email

String

Email address of the user

No

shortName

String

User's name for per-filling user registeration

No

Response Parameters

Parameter Name
Type
Description

success

Boolean

Success status of the request

code

ENUM

To see list of response codes go here.

message

String

Short message about code

transactionId

String

Unique Transaction ID generated by the merchant to track this request to PhonePe

merchantId

String

Unique Merchant ID assigned to the merchant by PhonePe

amount

Long

Transaction amount in paise

status

String

Status of the request

merchantUserId

String

Unique ID assigned to the user by the merchant. This is used for linking the user’s PhonePe account.

mobileNumber

String

Mobile number of the user

providerReferenceId

String

PhonePe transaction id

payResponseCode

String

PhonePe internal status code

{
  "merchantId": "DemoMerchant",
  "transactionId": "TX123456789",
  "merchantUserId": "U123456789",
  "amount": 100,
  "merchantOrderId": "OD1234",
  "subMerchant": "DemoMerchant",
  "mobileNumber": "9xxxxxxxxx",
  "message": "refund for cancelled order",
  "email": "amitxxx75@gmail.com",
  "shortName": "Amit"
}
{
  "request": "eyJtZXJjaGFudE9yZGVySWQiOiAiT0QxMjM0IiwgInN1Yk1lcmNoYW50IjogIkRlbW9NZXJjaGFudCIsICJhbW91bnQiOiAxMDAsICJtZXNzYWdlIjogInJlZnVuZCBmb3IgY2FuY2VsbGVkIG9yZGVyIiwgIm1vYmlsZU51bWJlciI6ICI5eHh4eHh4eHh4IiwgInNob3J0TmFtZSI6ICJBbWl0IiwgInRyYW5zYWN0aW9uSWQiOiAiVFgxMjM0NTY3ODkiLCAibWVyY2hhbnRVc2VySWQiOiAiVTEyMzQ1Njc4OSIsICJtZXJjaGFudElkIjogIkRlbW9NZXJjaGFudCIsICJlbWFpbCI6ICJhbWl0eHh4NzVAZ21haWwuY29tIn0"
}

Linking APIs

 


This section details the APIs you need to work with to trigger OTP, verify OTP and unlinking account on your integration using PhonePe and for handling operational issues related to payments.

Verify VPA

This API is used to check if the given VPA is valid or not.

 
gethttps://mercury-uat.phonepe.com/v3/vpa/merchantId/vpa/validate
curl --request GET \
  --url https://mercury-uat.phonepe.com/v3/vpa/M2306160483220675579140/adityajain27%40ybl/validate \
  --header 'content-type: application/json' \
  --header 'x-verify: 5024dbd7ef52a84b5db63431b9ce34fa055deadca08a16a8480c0649da1cee16###1'
var request = require("request");

var options = { method: 'GET',
  url:
   'https://mercury-uat.phonepe.com/v3/vpa/M2306160483220675579140/adityajain27%40ybl/validate',
  headers:
   { 'x-verify':
      '5024dbd7ef52a84b5db63431b9ce34fa055deadca08a16a8480c0649da1cee16###1',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/vpa/M2306160483220675579140/adityajain27%40ybl/validate")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = '5024dbd7ef52a84b5db63431b9ce34fa055deadca08a16a8480c0649da1cee16###1'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://mercury-uat.phonepe.com/v3/vpa/M2306160483220675579140/adityajain27%40ybl/validate");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "5024dbd7ef52a84b5db63431b9ce34fa055deadca08a16a8480c0649da1cee16###1");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/vpa/M2306160483220675579140/adityajain27%40ybl/validate"

headers = {
    'content-type': "application/json",
    'x-verify': "5024dbd7ef52a84b5db63431b9ce34fa055deadca08a16a8480c0649da1cee16###1"
    }

response = requests.request("GET", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
   "success": true,
   "code": "SUCCESS",
   "message": "Your request has been successfully completed.",
   "data": {
       "exists": true,
       "name": "Arun",
       "vpa": "arunsharma@ybl"
   }
}
{
   "success": false,
   "code": "EXTERNAL_VPA_ERROR",
   "message": "Incorrect UPI details. Please check the UPI ID entered.",
   "data": {}
}
{
   "success": false,
   "code": "BAD_REQUEST",
   "message": "Please check the inputs you have provided.",
   "data": {}
}

Path Params

merchantId
string
required

Unique Merchant ID assigned to the merchant by PhonePe

vpa
string
required

VPA (UPI ID) for which validation is required

Headers

Content-Type
string
required
X-VERIFY
string
required

SHA256("/v3/vpa/{merchantId}/{vpa}/validate" + saltKey) + "###" + saltIndex

 

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256("/v3/{merchantId}/{vpa}/validate" +
saltKey) + "###" + saltIndex

Path Parameters

Parameter Name
Type
Description
Mandatory

merchantId

STRING

Unique Merchant ID assigned to the merchant by PhonePe

Yes

vpa

STRING

VPA (UPI ID) for which validation is required

Yes

Response Parameters

Parameter Name
Type
Description

success

BOOLEAN

A boolean to indicate the success/failure of the request. Merchant should check for this parameter if VPA exists or not

code

ENUM(see list of codes below)

This parameter is used to decide if collect was successfully sent or not.

message

STRING

Short message about status of VPA

exists

BOOLEAN

Flag indicates if VPA (UPI ID) exists

name

STRING

Name of the person registered on this VPA

vpa

STRING

VPA ID passed in request

Response Codes

Code
Description

EXTERNAL_VPA_ERROR

Incorrect VPA. VPA ID does not exists.

BAD_REQUEST

Some mandatory parameter was missing

AUTHORIZATION_FAILED

Checksum sent in header was not valid

INTERNAL_SERVER_ERROR

Something went wrong

To check if a VPA is valid, Merchant should consider the following values:
success:true, code:"SUCCESS", exists:true

The value of data would be populated only if value of success is true.

Trigger OTP

API to send otp to customer’s mobile number and otpToken to merchant’s server side. This doesn’t involve any UI flow. Merchant needs to implement their own UI.

 
posthttps://mercury-uat.phonepe.com/v3/merchant/otp/send
curl --request POST \
  --url https://mercury-uat.phonepe.com/v3/merchant/otp/send \
  --header 'content-type: application/json' \
  --header 'x-verify: X-VERIFY'
var request = require("request");

var options = { method: 'POST',
  url: 'https://mercury-uat.phonepe.com/v3/merchant/otp/send',
  headers:
   { 'x-verify': 'X-VERIFY',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/merchant/otp/send")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = 'X-VERIFY'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://mercury-uat.phonepe.com/v3/merchant/otp/send");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "X-VERIFY");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/merchant/otp/send"

headers = {
    'content-type': "application/json",
    'x-verify': "X-VERIFY"
    }

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
 "success": true,
 "code": "SUCCESS",
 "message": "Your request has been successfully completed.",
 "data": {
   "merchantId": "M2306160483220675579140",
   "otpToken": "OTP7c8d7de8-5d16-46b7-a269-45afeafb5f8e"
 }
}

Body Params

request
string
required

base64 encoded payload

Headers

Content-Type
string
required
X-VERIFY
string
required

sha256(base64encodedpayload + '/v3/merchant/otp/send' + saltKey) + “###” + saltIndex

 

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256(base64 encoded payload +
'/v3/merchant/otp/send' + salt key) +
'###' + salt index

Request Parameters

Parameter Name
Type
Description
Mandatory

merchantId

string

Unique merchantId assigned to the merchant

Yes

mobileNumber

string

Mobile Number on which OTP will be sent

Yes

email

string

Email ID of the customer

No

shortName

string

Name of the customer

No

Response Parameters

Parameter Name
Type
Description

success

boolean

Denotes if API call is successful.

code

string

See below for list of values

data

Object

See below table

Response Codes

Code Value
Description

SUCCESS

Success scenario

AUTHORIZATION_FAILED

Value of X-VERIFY is incorrect

BAD_REQUEST

Invalid request payload

INTERNAL_SERVER_ERROR

The server is busy or the server is not responding

USER_BLACKLISTED

Customer is blacklisted on PhonePe side

USER_BLOCKED

User is blocked for 1 day.

OTP_LIMIT_EXCEEDED

There is a limit on number of times OTP can be sent on a mobile number. This code will be received is that limit is crossed.

TOO_MANY_REQUESTS

If we are getting too many requests from merchant for this API

Response Data

merchantId

string

merchantId assigned to merchant.

otpToken

string

OTP token (need to be passed while verifying the OTP)

otpToken should be stored in the server side and should not be passed to the client side.

{
 "merchantId": "MID",
 "mobileNumber": "9876543210",
 "email": "nishant.m@gmail.com",
 "shortName": "Nishant Mittal"
}
{
 "request" : "ew0KCeKAnG1lcmNoYW50SWTigJ06IOKAnEpJT+KAnSwNCgnigJx0cmFuc2FjdGlvbklk4oCdOiDigJxUWE4xMjM0NeKAnSwNCgnigJxtZXJjaGFudE9yZGVySWTigJ0gOiDigJxPNDIzODTigJ0sDQoJ4oCcbW9iaWxlTnVtYmVy4oCdOiDigJw5ODc2NTQzMjEw4oCdLA0KCeKAnG1lcmNoYW50VXNlcklk4oCdOiDigJxVU0VSMTIzNDXigJ0sDQoJ4oCcZW1haWw6IOKAnG5pc2hhbnQubUBnbWFpbC5jb23igJ0sDQoJ4oCcc2hvcnROYW1l4oCdIDog4oCcTmlzaGFudCBNaXR0YWzigJ0NCn0="
}

Verify OTP and Linking

API to verify the OTP given by the customer and the otpToken given by the merchant. Once verified merchant account is linked to PhonePe account. This doesn’t involve any UI flow. Merchant needs to implement their own UI.

 
posthttps://mercury-uat.phonepe.com/v3/merchant/otp/verify
curl --request POST \
  --url https://mercury-uat.phonepe.com/v3/merchant/otp/verify \
  --header 'content-type: application/json' \
  --header 'x-verify: X-VERIFY'
var request = require("request");

var options = { method: 'POST',
  url: 'https://mercury-uat.phonepe.com/v3/merchant/otp/verify',
  headers:
   { 'x-verify': 'X-VERIFY',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/merchant/otp/verify")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = 'X-VERIFY'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://mercury-uat.phonepe.com/v3/merchant/otp/verify");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "X-VERIFY");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/merchant/otp/verify"

headers = {
    'content-type': "application/json",
    'x-verify': "X-VERIFY"
    }

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
 "success": true,
 "code": "SUCCESS",
 "message": "Your request has been successfully completed.",
 "data": {
   "userAuthToken": "M23061604832206755791408c38b65b84314a3293b8eb9a5ad43079"
 }
}

Body Params

request
string
required

base64 encoded payload

Headers

Content-Type
string
required
X-VERIFY
string
required

sha256(base64encodedRequest + "/v3/merchant/otp/verify"+ saltKey) + “###” + saltIndex

 

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256(base64 encoded payload +
'/v3/merchant/otp/verify' + salt key) +
'###' + salt index

Request Parameters

Parameter Name
Type
Description
Mandatory

merchantId

string

Unique merchantId assigned to the merchant

Yes

otpToken

string

OTP token received in Trigger OTP API response

Yes

otp

string

OTP received by customer

Yes

PhonePe will send a new otpToken for every otp requested. Merchants need to pass the correct and latest otpToken and otp pair.

Response Parameters

Parameter Name
Type
Description

success

boolean

Denotes if API call is successful.

code

string

See below for list of values

data

Object

See below table

Response Code

Code Value
Description

SUCCESS

Success scenario

AUTHORIZATION_FAILED

Value of X-VERIFY is incorrect

BAD_REQUEST

Invalid request payload

INTERNAL_SERVER_ERROR

The server is busy or the server is not responding

USER_BLACKLISTED

Customer is blacklisted on PhonePe side

USER_BLOCKED

User is blocked for 1 day.

INVALID_OTP_TOKEN

OTP token is not valid or expired

OTP_LIMIT_EXCEEDED

There is a limit on number of times OTP can be sent on a mobile number. This code will be received is that limit is crossed.

OTP_ALREADY_VERIFIED

The OTP has been already verified for OTP token. Resending of OTP is required.

OTP_VERIFY_FAILED

Otp is invalid. Ask user to enter again

OTP_EXPIRED

Otp expired, regenerate again

TOO_MANY_REQUESTS

If we are getting too many requests from merchant for this API

Response Data

Parameter Name
Type
Description

merchantId

string

merchantId assigned to merchant.

userAuthToken

string

Auth token for the user

{
 "merchantId": "MID",
 "otpToken": "TXN12345",
 "otp": "65732"
}
{
 "request" : "ew0KCeKAnG1lcmNoYW50SWTigJ06IOKAnEpJT+KAnQ0KCeKAnHRyYW5zYWN0aW9uSWTigJ06IOKAnFRYTjEyMzQ14oCdLA0KCeKAnE90cOKAnTog4oCcNjU3MzLigJ0NCn0="
}

Get Wallet Balance

Used before initiating a payment transaction to check the instruments available for payment, along with usable balance in the wallet.

 
gethttps://mercury-uat.phonepe.com/v3/account/token/merchantId/userAuthToken/debit/suggest
curl --request GET \
  --url https://mercury-uat.phonepe.com/v3/account/token/M2306160483220675579140/M23061604832206755791408c38b65b84314a3293b8eb9a5ad43079/debit/suggest \
  --header 'content-type: application/json' \
  --header 'x-verify: 73d07ad1f4f67e33c881f724a435dccb7fdca6417fd28af609e736311911d28c###1'
var request = require("request");

var options = { method: 'GET',
  url:
   'https://mercury-uat.phonepe.com/v3/account/token/M2306160483220675579140/M23061604832206755791408c38b65b84314a3293b8eb9a5ad43079/debit/suggest',
  headers:
   { 'x-verify':
      '73d07ad1f4f67e33c881f724a435dccb7fdca6417fd28af609e736311911d28c###1',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/account/token/M2306160483220675579140/M23061604832206755791408c38b65b84314a3293b8eb9a5ad43079/debit/suggest")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = '73d07ad1f4f67e33c881f724a435dccb7fdca6417fd28af609e736311911d28c###1'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://mercury-uat.phonepe.com/v3/account/token/M2306160483220675579140/M23061604832206755791408c38b65b84314a3293b8eb9a5ad43079/debit/suggest");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "73d07ad1f4f67e33c881f724a435dccb7fdca6417fd28af609e736311911d28c###1");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/account/token/M2306160483220675579140/M23061604832206755791408c38b65b84314a3293b8eb9a5ad43079/debit/suggest"

headers = {
    'content-type': "application/json",
    'x-verify': "73d07ad1f4f67e33c881f724a435dccb7fdca6417fd28af609e736311911d28c###1"
    }

response = requests.request("GET", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "success": true,
  "code": "SUCCESS",
  "message": "Your request has been successfully completed.",
  "data": {
    "merchantId": "DemoMerchant",
    "allowPartialPayment": "no",
    "message": "Your request has been successfully completed.",
    "upi": {
      "enabled": true,
      "primaryAccount": "XXXXXXXX909"
    },
    "wallet": {
      "availableBalance": 400000,
      "usableBalance": 400000,
      "state": "ACTIVATED",
      "responseCode": "SUCCESS"
    }
  }
}
{
  "success": false,
  "code": "MERCHANT_USER_NOT_FOUND",
  "message": "The requested user doesn't seem to exist.",
  "data": {
    "merchantId": "DemoMerchant",
    "allowPartialPayment": "no",
    "upi": {},
    "wallet": {}
  }
}

Path Params

merchantId
string
required

Use Unique Merchant ID assigned to the merchant by PhonePe

userAuthToken
string
required

Auth token for the user.

Headers

Content-Type
string
required
X-VERIFY
string
required

SHA256("/v3/account/token/{merchantId}/{userAuthToken}/debit/suggest" + saltKey) + "###" + saltIndex

 

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256("/v3/account/token/{merchantId}/{userAuthToken}
/debit/suggest" + saltKey) + "###" + saltIndex

Path Parameters

Parameter Name
Type
Description
Mandatory

merchantId

String

Unique Merchant ID assigned to the merchant by PhonePe

Yes

userAuthToken

String

Unique userAuthToken given to merchant in OTP flow. This field is mandatory to get the user’s balance and available instruments.
Note :
Used only for OTP linking flow.

Yes

Response Parameters

Parameter Name
Type
Description

success

Boolean

Success status of the request

code

String

Refer to Response Code below for list of codes

message

String

Short message about status

merchantId

String

Unique Merchant ID assigned to the merchant by PhonePe

allowPartialPayment

String

Whether partial payment against various instruments is allowed

enabled

Boolean

Whether UPI is enabled for the user

primaryAccount

String

Primary bank account added to PhonePe account

availableBalance

Long

Available balance in PhonePe wallet

usableBalance

Long

Usable balance from PhonePe wallet

state

String

Wallet State

responseCode

String

Response Code for wallet information

Response Codes

The code in the above API response could be

  • SUCCESS
  • INTERNAL_SERVER_ERROR
  • MERCHANT_USER_NOT_FOUND :
  • INVALID_USER_AUTH_TOKEN : Token Expired. Show the linking flow to get new Token
  • INTERNAL_SERVER_ERROR : The server is busy or the server is not responding. Re hit the server.
  • USER_BLACKLISTED : Customer is blacklisted on PhonePe side
  • USER_BLOCKED : User is blocked for 1 day

Direct Wallet Debit

API to debit the money directly from PhonePe wallet.

 
posthttps://mercury-uat.phonepe.com/v3/debit/instant
curl --request POST \
  --url https://mercury-uat.phonepe.com/v3/debit/instant \
  --header 'content-type: application/json' \
  --header 'x-verify: X-VERIFY'
var request = require("request");

var options = { method: 'POST',
  url: 'https://mercury-uat.phonepe.com/v3/debit/instant',
  headers:
   { 'x-verify': 'X-VERIFY',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/debit/instant")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = 'X-VERIFY'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://mercury-uat.phonepe.com/v3/debit/instant");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "X-VERIFY");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/debit/instant"

headers = {
    'content-type': "application/json",
    'x-verify': "X-VERIFY"
    }

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
 "success": true,
 "code": "PAYMENT_SUCCESS",
 "message": "Your payment is successful.",
 "data": {
   "transactionId": "TXtest2dfws3dfd124",
   "amount": 10,
   "merchantId": "M2306160483220675579140",
   "merchantUserId": null,
   "status": "SUCCESS",
   "mobileNumber": "9611640370",
   "providerReferenceId": "P1801082016589589866175",
   "payResponseCode": "SUCCESS"
 }
}

Body Params

request
string
required

base64 encoded payload

Headers

Content-Type
string
required
X-VERIFY
string
required

sha256(base64encodedRequest + '/v3/debit/instant' + saltKey) + “###” + saltIndex

 

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256(base64 encoded payload +
' /v3/debit/instant' + salt key) +
'###' + salt index

Request Parameters

Parameter Name
Type
Description
Mandatory

merchantId

string

Unique merchant id assigned to the merchant

Yes

transactionId

string

Unique Transaction ID generated by the merchant to track this request to PhonePe

Yes

amount

int

Amount in paise

Yes

mobileNumber

string

Mobile number on which OTP will be sent

Yes

merchantOrderId

string

Order ID for the merchant transaction

Yes

userAuthToken

string

Auth token generated from otp verify

Yes

email

string

Email id of customer

No

shortName

string

Name of customer

No

Response Parameters

Parameter Name
Type
Description

success

boolean

Denotes if API call is successful.

code

string

See below for list of values

data

object

See below table

message

string

Short message about code

Response Codes

Code
Description

INVALID_TRANSACTION_ID

Duplicate TransactionID

BAD_REQUEST

Invalid request payload

AUTHORIZATION_FAILED

Incorrect X-VERIFY header

INTERNAL_SERVER_ERROR

Something went wrong

INVALID_USER_AUTH_TOKEN

The userAuthToken provided is either invalid or not mapped to merchant.

PAYMENT_SUCCESS

Payment is successful

PAYMENT_ERROR

Payment failed

USER_BLACKLISTED

Customer is blacklisted on PhonePe side

MERCHANT_USER_NOT_FOUND

No user exists for merchant id and user id combination.

USER_BLOCKED

User is blocked for 1 day.

TIMED_OUT

Payment timed out (Status check is required)

Response Data

Parameter Name
Type
Description

transactionId

String

Unique Transaction ID generated by the merchant to track this request to PhonePe

merchantId

String

Unique Merchant ID assigned to the merchant by PhonePe

amount

Long

Transaction amount in paise

status

String

Status of the request

merchantUserId

String

Unique ID assigned to the user by the merchant. This is used for linking the user’s PhonePe account.

mobileNumber

String

Mobile number of the user

providerReferenceId

String

PhonePe transaction id

payResponseCode

String

PhonePe internal status code

{
 "merchantId": "DemoMerchant",
 "transactionId": "TX123456789",
 "userAuthToken":"1604832205579140b0931ce0abbb450b9a40e81ed06ce216",
 "amount": 100,
 "merchantOrderId": "OD1234",
 "subMerchant": "DemoMerchant",
 "message": "Payment for order OD1234"
}
{
 "request" : "ew0KCeKAnG1lcmNoYW50SWTigJ06IOKAnEpJT+KAnSwNCgnigJx0cmFuc2FjdGlvbklk4oCdOiDigJxUWE4xMjM0NeKAnSwNCgnigJxtZXJjaGFudE9yZGVySWTigJ0gOiDigJxPNDIzODTigJ0sDQoJ4oCcbW9iaWxlTnVtYmVy4oCdOiDigJw5ODc2NTQzMjEw4oCdLA0KCeKAnG1lcmNoYW50VXNlcklk4oCdOiDigJxVU0VSMTIzNDXigJ0sDQoJ4oCcZW1haWw6IOKAnG5pc2hhbnQubUBnbWFpbC5jb23igJ0sDQoJ4oCcc2hvcnROYW1l4oCdIDog4oCcTmlzaGFudCBNaXR0YWzigJ0NCn0="
}

New : Direct Debit API

API to pay using wallet directly.

 
posthttps://mercury-uat.phonepe.com/v3/merchant/inline/pay
curl --request POST \
  --url https://mercury-uat.phonepe.com/v3/merchant/inline/pay \
  --header 'content-type: application/json' \
  --header 'x-verify: X-VERIFY'
var request = require("request");

var options = { method: 'POST',
  url: 'https://mercury-uat.phonepe.com/v3/merchant/inline/pay',
  headers:
   { 'x-verify': 'X-VERIFY',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/merchant/inline/pay")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = 'X-VERIFY'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://mercury-uat.phonepe.com/v3/merchant/inline/pay");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "X-VERIFY");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/merchant/inline/pay"

headers = {
    'content-type': "application/json",
    'x-verify': "X-VERIFY"
    }

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{  
   "success":true,
   "code":"PAYMENT_INITIATED",
   "data":{  
      "redirectUrl":"https://mercury.phonepe.com/1234" 
   }
}

Body Params

request
string
required

base64 encoded payload

Headers

Content-Type
string
required
X-VERIFY
string
required

SHA256(base64 encoded payload + "/v3/merchant/inline/pay" + salt key) + ### + salt index

X-REDIRECT-URL
string

Dynamic redirect URI for UI callback

X-REDIRECT-MODE
string

HTTP mode to be used for UI callback. Default Values are REDIRECT/POST.

X-CALLBACK-URL
string

Dynamic callback URI for server to server callback

X-CALL-MODE
string

HTTP mode to be used for server to server callback. Default Values are POST/PUT

 

If the code is PAYMENT_INITIATED, need to check status of the transaction using transaction status API.

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256(base64 encoded payload + "/v3/merchant/inline/pay" +
salt key) + ### + salt index

Request Parameters

Parameter Name
Type
Description
Mandatory

merchantId

STRING

Unique MerchantID assigned to the merchant by PhonePe

Yes

transactionId

STRING

Unique merchant transaction id (merchants do a status check etc using this id).

Yes

merchantUserId/ userAuthToken

STRING

User Id to identify user / token generated while linking user

Yes

amount

LONG

Transaction amount in Paise

Yes

merchantOrderId

STRING

Merchant order id

No

paymentSources

ARRAY

List of payment sources (explained below)

Yes

mobileNumber

STRING

Customers' mobile number

Yes

Response Codes

CODE
Despcription

PAYMENT_INITIATED

Success scenario - will contain redirect url

AUTHORIZATION_FAILED

Value of X-VERIFY is incorrect

BAD_REQUEST

Some mandatory parameter is missing

INTERNAL_SERVER_ERROR

Something went wrong

INVALID_TRANSACTION_ID

If the transaction id is not unique

INVALID_TRANSACTION_ID

Duplicate TransactionID

INVALID_USER_AUTH_TOKEN

The userAuthToken provided is either invalid or not mapped to merchant.

USER_BLACKLISTED

Customer is blacklisted on PhonePe side

MERCHANT_USER_NOT_FOUND

No user exists for merchant id and user id combination.

USER_BLOCKED

User is blocked for 1 day.

Transaction status check API:

After user is redirected to merchant page after completing the transaction, you can get the
status of transaction using transaction status api. Please use this link for reference.

{  
   "merchantId":"TESTMERCHANT",
   "transactionId":"TX1234",
   "merchantOrderId":"ORDERID",
   "merchantUserId":"TXX",
   "mobileNumber":"9123456789",
   "amount":100, //total amount
   "paymentSources":[  
      {  
         "mode":"wallets",
         "providers":[  //taking list here for multiple wallet providers
            "PHONEPE" 
         ]
      }
   ]
}
{  
 "request": "<Base64Encode>"
}

Unlinking

Used to unlink the PhonePe account with Merchant account of customer. The userAuthToken is also invalidated. This doesn’t involve any UI flow. Merchant needs to implement their own UI.

 
posthttps://mercury-uat.phonepe.com/v3/merchant/token/unlink
curl --request POST \
  --url https://mercury-uat.phonepe.com/v3/merchant/token/unlink \
  --header 'content-type: application/json' \
  --header 'x-verify: X-VERIFY'
var request = require("request");

var options = { method: 'POST',
  url: 'https://mercury-uat.phonepe.com/v3/merchant/token/unlink',
  headers:
   { 'x-verify': 'X-VERIFY',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/merchant/token/unlink")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = 'X-VERIFY'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://mercury-uat.phonepe.com/v3/merchant/token/unlink");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "X-VERIFY");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/merchant/token/unlink"

headers = {
    'content-type': "application/json",
    'x-verify': "X-VERIFY"
    }

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
 "success": true,
 "code": "SUCCESS",
 "message": "Your request has been successfully completed.",
 "data": {
   "merchantId": "M2306160483220675579140",
   "userAuthToken": "M23061604832206755791408c38b65b84314a3293b8eb9a5ad43079"
 }
}

Body Params

request
string
required

base64 encoded payload

Headers

Content-Type
string
required
X-VERIFY
string
required

sha256(base64encodedRequest + "/v3/merchant/token/unlink" + saltKey) + "###" + saltIndex

 

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256(base64 encoded payload +
'/v3/merchant/token/unlink' + salt key) +
'###' + salt index

Request Parameters

Parameter Name
Type
Description

merchantId

string

Unique merchantId assigned to merchant.

userAuthToken

string

Auth token for the user

Response Parameters

Parameter Name
Type
Description

success

boolean

Denotes if API call is successful.

code

string

See below for list of values

data

Object

See below table

Response Codes

Code Value
Description

SUCCESS

Success scenario

AUTHORIZATION_FAILED

Value of X-VERIFY is incorrect

BAD_REQUEST

Invalid request payload

INTERNAL_SERVER_ERROR

The server is busy or the server is not responding

USER_BLACKLISTED

Customer is blacklisted on PhonePe side

INVALID_USER_AUTH_TOKEN

The userAuthToken provided is either invalid or not mapped to merchant.

Response Data

Parameter Name
Type
Description

merchantId

string

merchantId assigned to merchant.

userAuthToken

string

The disabled Auth token for the user

{
 "merchantId": "MID",
 "userAuthToken": "TXN12345"
}
{
 "request" : "ew0KCeKAnG1lcmNoYW50SWTigJ06IOKAnE1JROKAnQ0KCeKAnHVzZXJBdXRoVG9rZW7igJ06IOKAnFRYTjEyMzQ14oCdLA0KfQ0K"
}

QC APIs

 

Get payment options API

API to get payment options for a user

 
posthttps://mercury-uat.phonepe.com/v3/merchant/payment/options
curl --request POST \
  --url https://mercury-uat.phonepe.com/v3/merchant/payment/options \
  --header 'content-type: application/json'
var request = require("request");

var options = { method: 'POST',
  url:
   'https://mercury-uat.phonepe.com/v3/merchant/payment/options',
  headers:
   { 'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/merchant/payment/options")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://mercury-uat.phonepe.com/v3/merchant/payment/options");
xhr.setRequestHeader("content-type", "application/json");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/merchant/payment/options"

headers = {'content-type': 'application/json'}

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{  
   "success":true,
   "code":"SUCCESS",
   "data":{  
      "wallets":{  
         "enabled":true,
         "instrumentPriority":1, //instrument level priority
         "activeWallets":[  //future provision for additional wallets
            {  
               "provider":"PHONEPE",
               "availableBalance":7675,
               "usableBalance":7675,
               "priority":0
            }
         ]
      },
      "upi":{  
         "enabled":true,
         "instrumentPriority":2,
         "deviceMapped":false, //for inline UPI payments
         "activeAccounts":[  
            {  
               "accountId":"AC1802131629137902917383",
               "priority":0, //priority inside each instrument
               "accountNo":"XXXXXXXXXX55743",
               "accountHolderName":"ABC",
               "bankName":"Test Bank - AABF",
               "offers":[  
                  {  
                     "offerId":"String",
                     "displayTitle":"String",
                     "description":"String",
                     "offerAmount":"Long",
                     "offerType":"String",
                     "tncLink":"String"
                  }
               ]
            }
         ]
      },
      "card":{  
         "enabled":true,
         "instrumentPriority":0,
         "savedCards":[  
            {  
               "cardId":"C68D688C382F4D12BB963E8D38B9F1D2",
               "cardIssuer":"VISA",
               "priority":0,
               "type":"DEBIT_CARD",
               "cardNumber":"4143XXXXXXXX3449",
               "cardBin":"414312",
               "cardHolderName":"UK",
               "externalCardId":"XXXX",
               "cvvRequired":true,
               "offers":[  
                  {  
                     "offerId":"String",
                     "displayTitle":"String",
                     "description":"String",
                     "offerAmount":"Long",
                     "offerType":"String",
                     "tncLink":"String"
                  }
               ]
            }
         ]
      }
   }
}

Body Params

request
string
required

base64 encoded payload

Headers

Content-Type
string
required
X-VERIFY
string

SHA256(base64 encoded payload + "/v3/merchant/payment/options" + salt key) + ### + salt index

X-MERCHANT-DEVICE-ID
string

Collect encrypted device id from Android app

 

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256(base64 encoded payload +
"/v3/merchant/payment/options" +
salt key) + ### + salt index

Request Parameters

Parameter Name
Type
Description
Mandatory

merchantId

STRING

Unique MerchantID assigned to the merchant by PhonePe

Yes

merchantUserId/ userAuthToken

STRING

Token to identify
user (generated
while linking user)

Yes

amount

LONG

Transaction amount in Paise

Yes

merchantOrderId

STRING

Merchant order id

No

Response Parameters

Parameter Name
Type
Description

success

BOOLEAN

Success status of the request

code

ENUM

See list of response codes below

data

OBJECT

See the below for more details

Data will contain list of instruments. Currently supported are wallet, upi, card. This can increase in future to EGV etc. Only enabled instruments must be shown.

  • instrumentPriority​: This is instrument level priority. Priority 0 being the highest.
  • priority: ​This will be for priority inside an instrument. For eg: If 3 saved cards there, then this denotes which one should be shown in what order.
  • deviceMapped : ​For inline UPI use cases. If deviceId comes in incoming request and UPI is enabled** on that device then this field will be true. (Currently not applicable)

Response Codes

CODE
Despcription

SUCCESS

Success status of the request

AUTHORIZATION_FAILED

Value of X-VERIFY is incorrect

BAD_REQUEST

Some mandatory parameter is missing

INTERNAL_SERVER_ERROR

Something went wrong

USER_NOT_FOUND

Cannot resolve user

INVALID_USER_AUTH_TOKEN

Invalid userAuthToken

{  
   "merchantId":"M2306160483220675579140", // String Mandatory
   "amount":100, // String Mandatory
   "merchantOrderId":"ORDERID", // String Optional
   "merchantUserId":"TXX", // String Mandatory
}
{    
"request": "eyAgCiAgICJtZXJjaGFudElkIjoiTTIzMDYxNjA0ODMyMjA2NzU1NzkxNDAiLAogICAiYW1vdW50IjoxMDAsCiAgICJtZXJjaGFudE9yZGVySWQiOiJPUkRFUklEIiwKICAgIm1lcmNoYW50VXNlcklkIjoiVFhYIiwKfQ=="
}

Pay call with selected instrument

API to pay using selected instrument

 
posthttps://mercury-uat.phonepe.com/v3/merchant/inline/pay
curl --request POST \
  --url https://mercury-uat.phonepe.com/v3/merchant/inline/pay \
  --header 'content-type: application/json' \
  --header 'x-verify: X-VERIFY'
var request = require("request");

var options = { method: 'POST',
  url: 'https://mercury-uat.phonepe.com/v3/merchant/inline/pay',
  headers:
   { 'x-verify': 'X-VERIFY',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/merchant/inline/pay")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = 'X-VERIFY'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://mercury-uat.phonepe.com/v3/merchant/inline/pay");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "X-VERIFY");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/merchant/inline/pay"

headers = {
    'content-type': "application/json",
    'x-verify': "X-VERIFY"
    }

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{  
   "success":true,
   "code":"PAYMENT_INITIATED",
   "data":{  
      "redirectUrl":"https://mercury.phonepe.com/1234"
   }
}
{  
   "success":true,
   "code":"PAYMENT_INITIATED",
   "message":"Payment initiated",
   "data":{  
      "intentURL":"upi://pay?pn=Test%20Merchant&pa=M2306160483220675579140@ybl&tid=YBL1be082ee36f
4495a9121724c6cd6f37d&tr=P1803141240039740504065&am=78.75&mam=78.75&cu=INR&u
rl=https://phonepe.com&mc=7299&tn=Payment%20for%20TX109090923",
      "package":"com.phonepe.app"
   }
}
{  
   "success":true,
   "code":"PAYMENT_INITIATED",
   "data":{  
      "redirectUrl":"https://mercury.phonepe.com/1234" 
   }
}

Body Params

request
string
required

base64 encoded payload

Headers

Content-Type
string
required
X-VERIFY
string
required

SHA256(base64 encoded payload + "/v3/merchant/inline/pay" + salt key) + ### + salt index

X-REDIRECT-URL
string

Dynamic redirect URI for UI callback

X-REDIRECT-MODE
string

HTTP mode to be used for UI callback. Default Values are REDIRECT/POST.

X-CALLBACK-URL
string

Dynamic callback URI for server to server callback

X-CALL-MODE
string

HTTP mode to be used for server to server callback. Default Values are POST/PUT

 

If the code is PAYMENT_INITIATED, need to check status of the transaction using transaction status API.

For UPI inline requests, device id is an extra parameter. User will get redirected to PhonePe using the redirect url in the response.

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256(base64 encoded payload + "/v3/merchant/inline/pay" +
salt key) + ### + salt index

Request Parameters

Parameter Name
Type
Description
Mandatory

merchantId

STRING

Unique MerchantID assigned to the merchant by PhonePe

Yes

transactionId

STRING

Unique merchant transaction id (merchants do a status check etc using this id).

Yes

merchantUserId/ userAuthToken

STRING

User Id to identify user / token generated while linking user

Yes

amount

LONG

Transaction amount in Paise

Yes

merchantOrderId

STRING

Merchant order id

No

paymentSources

ARRAY

List of payment sources (explained below)

Yes

deviceId

STRING

Flag to indicate if user is otp verified

No

Response Codes

CODE
Despcription

PAYMENT_INITIATED

Success scenario - will contain redirect url(in
case of card/wallet) / intent url(in case of UPI)

AUTHORIZATION_FAILED

Value of X-VERIFY is incorrect

BAD_REQUEST

Some mandatory parameter is missing

INTERNAL_SERVER_ERROR

Something went wrong

INVALID_TRANSACTION_ID

If the transaction id is not unique

PAYMENT_ERROR

If transaction fails due to reason not
mentioned above, like our payment service
fails or payment gateway is down

Transaction status check API:

After user is redirected to merchant page after completing the transaction, you can get the
status of transaction using transaction status api. Please use this link for reference.

{  
   "merchantId":"TESTMERCHANT",
   "transactionId":"TX1234",
   "merchantOrderId":"ORDERID",
   "merchantUserId":"TXX",
   "amount":100, //total amount
   "paymentSources":[  
      {  
         "mode":"card",
         "cardId":"C1234",
         "cardIssuer":"VISA",
         "type":"DEBIT_CARD",
         "cvv":"123",
         "cardHolderName":"PhonePe User"
      },
      {  
         "mode":"wallets",
         "providers":[  //taking list here for multiple wallet providers
            "PHONEPE" 
         ]
      }
   ]
}
{  
 "request": "eyAgDQogICAibWVyY2hhbnRJZCI6IlRFU1RNRVJDSEFOVCIsDQogICAidHJhbnNhY3Rpb25JZCI6IlRYMTIzNCIsDQogICAibWVyY2hhbnRPcmRlcklkIjoiT1JERVJJRCIsDQogICAibWVyY2hhbnRVc2VySWQiOiJUWFgiLA0KICAgIm1vYmlsZU51bWJlciI6IjkxMjM0NTY3ODkiLA0KICAgIm90cFZlcmlmaWVkIjp0cnVlLA0KICAgImFtb3VudCI6MTAwLCAvL3RvdGFsIGFtb3VudA0KICAgInBheW1lbnRTb3VyY2VzIjpbICANCiAgICAgIHsgIA0KICAgICAgICAgIm1vZGUiOiJjYXJkIiwNCiAgICAgICAgICJjYXJkSWQiOiJDMTIzNCIsDQogICAgICAgICAiY2FyZElzc3VlciI6IlZJU0EiLA0KICAgICAgICAgInR5cGUiOiJERUJJVF9DQVJEIiwNCiAgICAgICAgICJjdnYiOiIxMjMiLA0KICAgICAgICAgImNhcmRIb2xkZXJOYW1lIjoiUGhvbmVQZSBVc2VyIg0KICAgICAgfSwNCiAgICAgIHsgIA0KICAgICAgICAgIm1vZGUiOiJ3YWxsZXRzIiwNCiAgICAgICAgICJwcm92aWRlcnMiOlsgIA0KICAgICAgICAgICAgIlBIT05FUEUiIA0KICAgICAgICAgXSAvL3Rha2luZyBsaXN0IGhlcmUgZm9yIG11bHRpcGxlIHdhbGxldCBwcm92aWRlcnMNCiAgICAgIH0NCiAgIF0NCn0="
}
{  
   "merchantId":"TESTMERCHANT",
   "transactionId":"TX1234",
   "merchantOrderId":"ORDERID",
   "merchantUserId":"M1234",
   "amount":100, //total amount
   "deviceId":"D1234", //optional, to be provided by SDK
   "paymentSources":[  
      {  
         "mode":"upi",
         "type":"INLINE",
         "accountId":"AC1234"
      }
   ]
}
{  
 "request": "eyAgDQogICAibWVyY2hhbnRJZCI6IlRFU1RNRVJDSEFOVCIsDQogICAidHJhbnNhY3Rpb25JZCI6IlRYMTIzNCIsDQogICAibWVyY2hhbnRPcmRlcklkIjoiT1JERVJJRCIsDQogICAibWVyY2hhbnRVc2VySWQiOiJNMTIzNCIsDQogICAiYW1vdW50IjoxMDAsDQogICAiZGV2aWNlSWQiOiJEMTIzNCIsDQogICAicGF5bWVudFNvdXJjZXMiOlsgIA0KICAgICAgeyAgDQogICAgICAgICAibW9kZSI6InVwaSIsDQogICAgICAgICAidHlwZSI6IklOTElORSIsDQogICAgICAgICAiYWNjb3VudElkIjoiQUMxMjM0Ig0KICAgICAgfQ0KICAgXQ0KfQ=="
}
{  
   "merchantId":"M2306160483220675579140",
   "merchantUserId":"M230616048322067557914080161871162446f26da6d4b67",
   "amount":7875,
   "transactionId":"TX10909099992",
   "merchantOrderId":"TX109090923",
   "paymentSources":[  
      {  
         "mode":"upi",
         "type":"INTENT"
      }
   ]
}
{  
 "request": "eyAgDQogICAibWVyY2hhbnRJZCI6Ik0yMzA2MTYwNDgzMjIwNjc1NTc5MTQwIiwNCiAgICJtZXJjaGFudFVzZXJJZCI6Ik0yMzA2MTYwNDgzMjIwNjc1NTc5MTQwODAxNjE4NzExNjI0NDZmMjZkYTZkNGI2NyIsDQogICAiYW1vdW50Ijo3ODc1LA0KICAgIm1vYmlsZU51bWJlciI6Ijk3NDA0OTY4NjkiLA0KICAgInRyYW5zYWN0aW9uSWQiOiJUWDEwOTA5MDk5OTkyIiwNCiAgICJtZXJjaGFudE9yZGVySWQiOiJUWDEwOTA5MDkyMyIsDQogICAicGF5bWVudFNvdXJjZXMiOlsgIA0KICAgICAgeyAgDQogICAgICAgICAibW9kZSI6InVwaSIsDQogICAgICAgICAidHlwZSI6IklOVEVOVCINCiAgICAgIH0NCiAgIF0NCn0="
}
{  
   "merchantId":"TESTMERCHANT",
   "transactionId":"TX1234",
   "merchantOrderId":"ORDERID",
   "merchantUserId":"TXX",
   "amount":100, //total amount
   "paymentSources":[  
      {  
         "mode":"wallets",
         "providers":[  //taking list here for multiple wallet providers
            "PHONEPE" 
         ]
      }
   ]
}
{  
 "request": <Base64Encode>
}

Pay call with selected instrument

 
gethttps://mercury-uat.phonepe.com/v3/merchant/inline/pay
curl --request GET \
  --url https://mercury-uat.phonepe.com/v3/merchant/inline/pay \
  --header 'content-type: application/json' \
  --header 'x-verify: X-VERIFY'
var request = require("request");

var options = { method: 'GET',
  url: 'https://mercury-uat.phonepe.com/v3/merchant/inline/pay',
  headers:
   { 'x-verify': 'X-VERIFY',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/merchant/inline/pay")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = 'X-VERIFY'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://mercury-uat.phonepe.com/v3/merchant/inline/pay");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "X-VERIFY");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/merchant/inline/pay"

headers = {
    'content-type': "application/json",
    'x-verify': "X-VERIFY"
    }

response = requests.request("GET", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{  
   "success":true,
   "code":"PAYMENT_INITIATED",
   "data":{  
      "redirectUrl":"https://mercury.phonepe.com/1234"
   }
}
{  
   "success":true,
   "code":"PAYMENT_INITIATED",
   "message":"Payment initiated",
   "data":{  
      "intentURL":"upi://pay?pn=Test%20Merchant&pa=M2306160483220675579140@ybl&tid=YBL1be082ee36f
4495a9121724c6cd6f37d&tr=P1803141240039740504065&am=78.75&mam=78.75&cu=INR&u
rl=https://phonepe.com&mc=7299&tn=Payment%20for%20TX109090923",
      "package":"com.phonepe.app"
   }
}
{  
   "success":true,
   "code":"PAYMENT_INITIATED",
   "data":{  
      "redirectUrl":"https://mercury.phonepe.com/1234" 
   }
}

Body Params

request
string
required

base64 encoded payload

Headers

Content-Type
string
required
X-VERIFY
string
required

SHA256(base64 encoded payload + "/v3/merchant/inline/pay" + salt key) + ### + salt index

X-REDIRECT-URL
string

Dynamic redirect URI for UI callback

X-REDIRECT-MODE
string

HTTP mode to be used for UI callback. Default Values are REDIRECT/POST.

X-CALLBACK-URL
string

Dynamic callback URI for server to server callback

X-CALL-MODE
string

HTTP mode to be used for server to server callback. Default Values are POST/PUT

 

If the code is PAYMENT_INITIATED, need to check status of the transaction using transaction status API.

For UPI inline requests, device id is an extra parameter. User will get redirected to PhonePe using the redirect url in the response.

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256(base64 encoded payload + "/v3/merchant/inline/pay" +
salt key) + ### + salt index

Request Parameters

Parameter Name
Type
Description
Mandatory

merchantId

STRING

Unique MerchantID assigned to the merchant by PhonePe

Yes

transactionId

STRING

Unique merchant transaction id (merchants do a status check etc using this id).

Yes

merchantUserId/ userAuthToken

STRING

User Id to identify user / token generated while linking user

Yes

amount

LONG

Transaction amount in Paise

Yes

merchantOrderId

STRING

Merchant order id

No

paymentSources

ARRAY

List of payment sources (explained below)

Yes

deviceId

STRING

Flag to indicate if user is otp verified

No

Response Codes

CODE
Despcription

PAYMENT_INITIATED

Success scenario - will contain redirect url(in
case of card/wallet) / intent url(in case of UPI)

AUTHORIZATION_FAILED

Value of X-VERIFY is incorrect

BAD_REQUEST

Some mandatory parameter is missing

INTERNAL_SERVER_ERROR

Something went wrong

INVALID_TRANSACTION_ID

If the transaction id is not unique

PAYMENT_ERROR

If transaction fails due to reason not
mentioned above, like our payment service
fails or payment gateway is down

Transaction status check API:

After user is redirected to merchant page after completing the transaction, you can get the
status of transaction using transaction status api. Please use this link for reference.

{  
   "merchantId":"M2306160483220675579140",  // String Mandatory
   "transactionId":"TX1234",  // String Mandatory
   "merchantOrderId":"ORDERID",  // String Optional 
   "merchantUserId":"TXX",  // String Mandatory
   "amount":100,  //  Integer Mandatory
   "paymentSources":[  // Object Mandatory
      {  
         "mode":"card",   // String Mandatory 
         "cardId":"C1234",  // String Mandatory
         "cardIssuer":"VISA", // String Optional
         "type":"DEBIT_CARD", // String Optional
         "cvv":"123", // String Optional
         "cardHolderName":"PhonePe User" // String Optional
      },
      {  
         "mode":"wallets",  // String Mandatory 
         "providers":[  // String Mandatory - taking list here for multiple wallet providers
            "PHONEPE" 
         ]
      }
   ]
}
{  
 "request": "eyAgCiAgICJtZXJjaGFudElkIjoiTTIzMDYxNjA0ODMyMjA2NzU1NzkxNDAiLAogICAidHJhbnNhY3Rpb25JZCI6IlRYMTIzNCIsCiAgICJtZXJjaGFudE9yZGVySWQiOiJPUkRFUklEIiwKICAgIm1lcmNoYW50VXNlcklkIjoiVFhYIiwKICAgImFtb3VudCI6MTAwLCAvL3RvdGFsIGFtb3VudAogICAicGF5bWVudFNvdXJjZXMiOlsgIAogICAgICB7ICAKICAgICAgICAgIm1vZGUiOiJjYXJkIiwKICAgICAgICAgImNhcmRJZCI6IkMxMjM0IiwKICAgICAgICAgImNhcmRJc3N1ZXIiOiJWSVNBIiwKICAgICAgICAgInR5cGUiOiJERUJJVF9DQVJEIiwKICAgICAgICAgImN2diI6IjEyMyIsCiAgICAgICAgICJjYXJkSG9sZGVyTmFtZSI6IlBob25lUGUgVXNlciIKICAgICAgfSwKICAgICAgeyAgCiAgICAgICAgICJtb2RlIjoid2FsbGV0cyIsCiAgICAgICAgICJwcm92aWRlcnMiOlsgIC8vdGFraW5nIGxpc3QgaGVyZSBmb3IgbXVsdGlwbGUgd2FsbGV0IHByb3ZpZGVycwogICAgICAgICAgICAiUEhPTkVQRSIgCiAgICAgICAgIF0KICAgICAgfQogICBdCn0="
}
{  
   "merchantId":"M2306160483220675579140", // String Mandatory
   "transactionId":"TX1234", // String Mandatory
   "merchantOrderId":"ORDERID",   // String Optional
   "merchantUserId":"M1234", // String Mandatory
   "amount":100, // String Mandatory
   "deviceId":"D1234",// String Optional - Collect encrypted device Id from your android app.
   "paymentSources":[   // String Mandatory
      {  
         "mode":"upi",    // String Mandatory
         "type":"INLINE",   // String Mandatory
         "accountId":"AC1234"   // String Mandatory
      }
   ]
}
{  
 "request": "eyAgCiAgICJtZXJjaGFudElkIjoiTTIzMDYxNjA0ODMyMjA2NzU1NzkxNDAiLAogICAidHJhbnNhY3Rpb25JZCI6IlRYMTIzNCIsCiAgICJtZXJjaGFudE9yZGVySWQiOiJPUkRFUklEIiwKICAgIm1lcmNoYW50VXNlcklkIjoiTTEyMzQiLAogICAiYW1vdW50IjoxMDAsIC8vdG90YWwgYW1vdW50CiAgICJkZXZpY2VJZCI6IkQxMjM0IiwgLy9vcHRpb25hbCwgdG8gYmUgcHJvdmlkZWQgYnkgU0RLCiAgICJwYXltZW50U291cmNlcyI6WyAgCiAgICAgIHsgIAogICAgICAgICAibW9kZSI6InVwaSIsCiAgICAgICAgICJ0eXBlIjoiSU5MSU5FIiwKICAgICAgICAgImFjY291bnRJZCI6IkFDMTIzNCIKICAgICAgfQogICBdCn0="
}
{  
   "merchantId":"M2306160483220675579140",   // String Mandatory
   "merchantUserId":"M2306160487",   // String Mandatory
   "amount":7875,   // String Mandatory
   "transactionId":"TX10909099992",     // String Mandatory
   "merchantOrderId":"TX109090923",    // String Optional       
   "paymentSources":[     // String Mandatory
      {  
         "mode":"upi",   // String Mandatory
         "type":"INTENT"    // String Mandatory
      }
   ]
}
{  
 "request": "eyAgCiAgICJtZXJjaGFudElkIjoiTTIzMDYxNjA0ODMyMjA2NzU1NzkxNDAiLAogICAibWVyY2hhbnRVc2VySWQiOiJNMjMwNjE2MDQ4MzIyMDY3NTU3OTE0MDgwMTYxODcxMTYyNDQ2ZjI2ZGE2ZDRiNjciLAogICAiYW1vdW50Ijo3ODc1LAogICAidHJhbnNhY3Rpb25JZCI6IlRYMTA5MDkwOTk5OTIiLAogICAibWVyY2hhbnRPcmRlcklkIjoiVFgxMDkwOTA5MjMiLAogICAicGF5bWVudFNvdXJjZXMiOlsgIAogICAgICB7ICAKICAgICAgICAgIm1vZGUiOiJ1cGkiLAogICAgICAgICAidHlwZSI6IklOVEVOVCIKICAgICAgfQogICBdCn0="
}
{  
   "merchantId":"M2306160483220675579140",   // String Mandatory
   "transactionId":"TX1234",    // String Mandatory
   "merchantOrderId":"ORDERID",   // String Optional
   "merchantUserId":"TXX",   // String Mandatory
   "amount":100,  // String Mandatory
   "paymentSources":[      // String Mandatory
      {  
         "mode":"wallets",      // String Mandatory
         "providers":[    // String Mandatory - taking list here for multiple wallet providers
            "PHONEPE" 
         ]
      }
   ]
}

{  
 "request": "eyAgCiAgICJtZXJjaGFudElkIjoiVEVTVE1FUkNIQU5UIiwKICAgInRyYW5zYWN0aW9uSWQiOiJUWDEyMzQiLAogICAibWVyY2hhbnRPcmRlcklkIjoiT1JERVJJRCIsCiAgICJtZXJjaGFudFVzZXJJZCI6IlRYWCIsCiAgICJhbW91bnQiOjEwMCwgLy90b3RhbCBhbW91bnQKICAgInBheW1lbnRTb3VyY2VzIjpbICAKICAgICAgeyAgCiAgICAgICAgICJtb2RlIjoid2FsbGV0cyIsCiAgICAgICAgICJwcm92aWRlcnMiOlsgIC8vdGFraW5nIGxpc3QgaGVyZSBmb3IgbXVsdGlwbGUgd2FsbGV0IHByb3ZpZGVycwogICAgICAgICAgICAiUEhPTkVQRSIgCiAgICAgICAgIF0KICAgICAgfQogICBdCn0="
}

Inline pay call API

 
posthttps://mercury-uat.phonepe.com
curl --request POST \
  --url https://mercury-uat.phonepe.com/ \
  --header 'content-type: application/json' \
  --header 'x-verify: X-VERIFY'
var request = require("request");

var options = { method: 'POST',
  url: 'https://mercury-uat.phonepe.com/',
  headers:
   { 'x-verify': 'X-VERIFY',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = 'X-VERIFY'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://mercury-uat.phonepe.com/");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "X-VERIFY");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/"

headers = {
    'content-type': "application/json",
    'x-verify': "X-VERIFY"
    }

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{  
   "success":true,
   "code":"PAYMENT_INITIATED",
   "data":{  
      "redirectUrl":"https://mercury.phonepe.com/1234"
   }
}
{  
   "success":true,
   "code":"PAYMENT_INITIATED",
   "message":"Payment initiated",
   "data":{  
      "intentURL":"upi://pay?pn=Test%20Merchant&pa=M2306160483220675579140@ybl&tid=YBL1be082ee36f
4495a9121724c6cd6f37d&tr=P1803141240039740504065&am=78.75&mam=78.75&cu=INR&u
rl=https://phonepe.com&mc=7299&tn=Payment%20for%20TX109090923",
      "package":"com.phonepe.app"
   }
}
{  
   "success":true,
   "code":"PAYMENT_INITIATED",
   "data":{  
      "redirectUrl":"https://mercury.phonepe.com/1234" 
   }
}

Body Params

request
string
required

base64 encoded payload

Headers

Content-Type
string
required
X-VERIFY
string
required

SHA256(base64 encoded payload + "/v3/merchant/inline/pay" + salt key) + ### + salt index

X-REDIRECT-URL
string

Dynamic redirect URI for UI callback

X-REDIRECT-MODE
string

HTTP mode to be used for UI callback. Default Values are REDIRECT/POST.

X-CALLBACK-URL
string

Dynamic callback URI for server to server callback

X-CALL-MODE
string

HTTP mode to be used for server to server callback. Default Values are POST/PUT

 

If the code is PAYMENT_INITIATED, need to check status of the transaction using transaction status API.

For UPI inline requests, device id is an extra parameter. User will get redirected to PhonePe using the redirect url in the response.

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256(base64 encoded payload + "/v3/merchant/inline/pay" +
salt key) + ### + salt index

Request Parameters

Parameter Name
Type
Description
Mandatory

merchantId

STRING

Unique MerchantID assigned to the merchant by PhonePe

Yes

transactionId

STRING

Unique merchant transaction id (merchants do a status check etc using this id).

Yes

merchantUserId/ userAuthToken

STRING

User Id to identify user / token generated while linking user

Yes

amount

LONG

Transaction amount in Paise

Yes

merchantOrderId

STRING

Merchant order id

No

paymentSources

ARRAY

List of payment sources (explained below)

Yes

deviceId

STRING

Flag to indicate if user is otp verified

No

Response Codes

CODE
Despcription

PAYMENT_INITIATED

Success scenario - will contain redirect url(in
case of card/wallet) / intent url(in case of UPI)

AUTHORIZATION_FAILED

Value of X-VERIFY is incorrect

BAD_REQUEST

Some mandatory parameter is missing

INTERNAL_SERVER_ERROR

Something went wrong

INVALID_TRANSACTION_ID

If the transaction id is not unique

PAYMENT_ERROR

If transaction fails due to reason not
mentioned above, like our payment service
fails or payment gateway is down

Transaction status check API:

After user is redirected to merchant page after completing the transaction, you can get the
status of transaction using transaction status api. Please use this link for reference.

{  
   "merchantId":"M2306160483220675579140",  // String Mandatory
   "transactionId":"TX1234",  // String Mandatory
   "merchantOrderId":"ORDERID",  // String Optional 
   "merchantUserId":"TXX",  // String Mandatory
   "amount":100,  //  Integer Mandatory
   "paymentSources":[  // Object Mandatory
      {  
         "mode":"card",   // String Mandatory 
         "cardId":"C1234",  // String Mandatory
         "cardIssuer":"VISA", // String Optional
         "type":"DEBIT_CARD", // String Optional
         "cvv":"123", // String Optional
         "cardHolderName":"PhonePe User" // String Optional
      },
      {  
         "mode":"wallets",  // String Mandatory 
         "providers":[  // String Mandatory - taking list here for multiple wallet providers
            "PHONEPE" 
         ]
      }
   ]
}
{  
 "request": "eyAgCiAgICJtZXJjaGFudElkIjoiTTIzMDYxNjA0ODMyMjA2NzU1NzkxNDAiLAogICAidHJhbnNhY3Rpb25JZCI6IlRYMTIzNCIsCiAgICJtZXJjaGFudE9yZGVySWQiOiJPUkRFUklEIiwKICAgIm1lcmNoYW50VXNlcklkIjoiVFhYIiwKICAgImFtb3VudCI6MTAwLCAvL3RvdGFsIGFtb3VudAogICAicGF5bWVudFNvdXJjZXMiOlsgIAogICAgICB7ICAKICAgICAgICAgIm1vZGUiOiJjYXJkIiwKICAgICAgICAgImNhcmRJZCI6IkMxMjM0IiwKICAgICAgICAgImNhcmRJc3N1ZXIiOiJWSVNBIiwKICAgICAgICAgInR5cGUiOiJERUJJVF9DQVJEIiwKICAgICAgICAgImN2diI6IjEyMyIsCiAgICAgICAgICJjYXJkSG9sZGVyTmFtZSI6IlBob25lUGUgVXNlciIKICAgICAgfSwKICAgICAgeyAgCiAgICAgICAgICJtb2RlIjoid2FsbGV0cyIsCiAgICAgICAgICJwcm92aWRlcnMiOlsgIC8vdGFraW5nIGxpc3QgaGVyZSBmb3IgbXVsdGlwbGUgd2FsbGV0IHByb3ZpZGVycwogICAgICAgICAgICAiUEhPTkVQRSIgCiAgICAgICAgIF0KICAgICAgfQogICBdCn0="
}
{  
   "merchantId":"M2306160483220675579140", // String Mandatory
   "transactionId":"TX1234", // String Mandatory
   "merchantOrderId":"ORDERID",   // String Optional
   "merchantUserId":"M1234", // String Mandatory
   "amount":100, // String Mandatory
   "deviceId":"D1234",// String Optional - Collect encrypted device Id from your android app.
   "paymentSources":[   // String Mandatory
      {  
         "mode":"upi",    // String Mandatory
         "type":"INLINE",   // String Mandatory
         "accountId":"AC1234"   // String Mandatory
      }
   ]
}
{  
 "request": "eyAgCiAgICJtZXJjaGFudElkIjoiTTIzMDYxNjA0ODMyMjA2NzU1NzkxNDAiLAogICAidHJhbnNhY3Rpb25JZCI6IlRYMTIzNCIsCiAgICJtZXJjaGFudE9yZGVySWQiOiJPUkRFUklEIiwKICAgIm1lcmNoYW50VXNlcklkIjoiTTEyMzQiLAogICAiYW1vdW50IjoxMDAsIC8vdG90YWwgYW1vdW50CiAgICJkZXZpY2VJZCI6IkQxMjM0IiwgLy9vcHRpb25hbCwgdG8gYmUgcHJvdmlkZWQgYnkgU0RLCiAgICJwYXltZW50U291cmNlcyI6WyAgCiAgICAgIHsgIAogICAgICAgICAibW9kZSI6InVwaSIsCiAgICAgICAgICJ0eXBlIjoiSU5MSU5FIiwKICAgICAgICAgImFjY291bnRJZCI6IkFDMTIzNCIKICAgICAgfQogICBdCn0="
}
{  
   "merchantId":"M2306160483220675579140",   // String Mandatory
   "merchantUserId":"M2306160487",   // String Mandatory
   "amount":7875,   // String Mandatory
   "transactionId":"TX10909099992",     // String Mandatory
   "merchantOrderId":"TX109090923",    // String Optional       
   "paymentSources":[     // String Mandatory
      {  
         "mode":"upi",   // String Mandatory
         "type":"INTENT"    // String Mandatory
      }
   ]
}
{  
 "request": "eyAgCiAgICJtZXJjaGFudElkIjoiTTIzMDYxNjA0ODMyMjA2NzU1NzkxNDAiLAogICAibWVyY2hhbnRVc2VySWQiOiJNMjMwNjE2MDQ4MzIyMDY3NTU3OTE0MDgwMTYxODcxMTYyNDQ2ZjI2ZGE2ZDRiNjciLAogICAiYW1vdW50Ijo3ODc1LAogICAidHJhbnNhY3Rpb25JZCI6IlRYMTA5MDkwOTk5OTIiLAogICAibWVyY2hhbnRPcmRlcklkIjoiVFgxMDkwOTA5MjMiLAogICAicGF5bWVudFNvdXJjZXMiOlsgIAogICAgICB7ICAKICAgICAgICAgIm1vZGUiOiJ1cGkiLAogICAgICAgICAidHlwZSI6IklOVEVOVCIKICAgICAgfQogICBdCn0="
}
{  
   "merchantId":"M2306160483220675579140",   // String Mandatory
   "transactionId":"TX1234",    // String Mandatory
   "merchantOrderId":"ORDERID",   // String Optional
   "merchantUserId":"TXX",   // String Mandatory
   "amount":100,  // String Mandatory
   "paymentSources":[      // String Mandatory
      {  
         "mode":"wallets",      // String Mandatory
         "providers":[    // String Mandatory - taking list here for multiple wallet providers
            "PHONEPE" 
         ]
      }
   ]
}

{  
 "request": "eyAgCiAgICJtZXJjaGFudElkIjoiVEVTVE1FUkNIQU5UIiwKICAgInRyYW5zYWN0aW9uSWQiOiJUWDEyMzQiLAogICAibWVyY2hhbnRPcmRlcklkIjoiT1JERVJJRCIsCiAgICJtZXJjaGFudFVzZXJJZCI6IlRYWCIsCiAgICJhbW91bnQiOjEwMCwgLy90b3RhbCBhbW91bnQKICAgInBheW1lbnRTb3VyY2VzIjpbICAKICAgICAgeyAgCiAgICAgICAgICJtb2RlIjoid2FsbGV0cyIsCiAgICAgICAgICJwcm92aWRlcnMiOlsgIC8vdGFraW5nIGxpc3QgaGVyZSBmb3IgbXVsdGlwbGUgd2FsbGV0IHByb3ZpZGVycwogICAgICAgICAgICAiUEhPTkVQRSIgCiAgICAgICAgIF0KICAgICAgfQogICBdCn0="
}

Primary APIs

 

Get Payment options API

 

Server Side

1.Save the below assigned apiEndPoint value at your server for payment options.

String apiEndPoint = "/v3/merchant/payment/options";
  1. Call Get Payment Options API. Refer this link for more details.
  1. Select one of the API keys shared with you and note it's index. Refer this link for salt key value and salt index credentials. Construct the checksum at your server as follows:
String checksum = sha256(base64Body + apiEndPoint + salt) + ### + saltIndex;

App Side

  • Collect payment options API response and display payment option modes on the user interface.

Inline Pay call API

 

Server Side

1.Save the below assigned apiEndPoint value at your server for inline pay.

String apiEndPoint = "/v3/merchant/inline/pay";

2.Collect encrypted device Id from your app.

3.Call Inline Pay API. Refer this link for more details.

4.Select one of the API keys shared with you and note it's index. Refer this link for salt key value and salt index credentials. Construct the checksum at your server as follows:

String checksum = sha256(base64Body + apiEndPoint + salt) + ### + saltIndex;

App Side

  1. Get the device Id using the below code:
try {
   PhonePe.getDeviceId(this, new iDeviceIdListener() {
       @Override
       public void onDeviceIdAvailable(String s) {
           // Get encrypted device Id using the below code
       }
   });
} catch (PhonePeInitException e) {
   e.printStackTrace();
}

2.a Collect base64 encoded payload, checksum and apiEndPoint from your server.
b. Initiate the payment process as follows:

TransactionRequest debitRequest = new TransactionRequestBuilder()
       .setData(base64Body)
       .setChecksum(checksum)
       .setUrl(apiEndPoint)
       .build();

try {
   startActivityForResult(PhonePe.getTransactionIntent(this, debitRequest), DEBIT_REQUEST_CODE);
} catch (PhonePeInitException e) {
   e.printStackTrace();
}
  1. Override onActivityResult to listen to debit result:
private static int DEBIT_REQUEST_CODE = 777; 

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == DEBIT_REQUEST_CODE) {
      if (resultCode == Activity.RESULT_OK) {
            /*This callback indicates only about completion of UI flow.
            Inform your server to make the transaction
            status call to get the status. Update your app with the
            success/failure status.*/
            }
            else if (resultCode == Activity.RESULT_CANCELED) {
            /*This callback indicates that the transaction has been cancelled by the end user.
            Inform your server to make the transaction
            status call to get the status. Update your app with the
            failure status.*/
      }
    }   
}
  • Inform your server about the completion of the transaction flow from your app.
  • Your server should make the Check Transaction Status API call to PhonePe server to check the transaction status.
  • Get the result and notify your app.
  • Based on the result inform the user about success or failure status of the transaction.

Check Transaction Status

 
gethttps://mercury-uat.phonepe.com/v3/transaction/merchantId/transactionId/status
curl --request GET \
  --url https://mercury-uat.phonepe.com/v3/transaction/M2306160483220675579140/1511522079/status \
  --header 'content-type: Content-Type' \
  --header 'x-verify: 6ab24e24ae92646c82e0450f029478117d8a1a0a00390e266ea1178a0c68e419###1'
var request = require("request");

var options = { method: 'GET',
  url:
   'https://mercury-uat.phonepe.com/v3/transaction/M2306160483220675579140/1511522079/status',
  headers:
   { 'x-verify':
      '6ab24e24ae92646c82e0450f029478117d8a1a0a00390e266ea1178a0c68e419###1',
     'content-type': 'Content-Type' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/transaction/M2306160483220675579140/1511522079/status")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["content-type"] = 'Content-Type'
request["x-verify"] = '6ab24e24ae92646c82e0450f029478117d8a1a0a00390e266ea1178a0c68e419###1'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://mercury-uat.phonepe.com/v3/transaction/M2306160483220675579140/1511522079/status");
xhr.setRequestHeader("content-type", "Content-Type");
xhr.setRequestHeader("x-verify", "6ab24e24ae92646c82e0450f029478117d8a1a0a00390e266ea1178a0c68e419###1");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/transaction/M2306160483220675579140/1511522079/status"

headers = {
    'content-type': "Content-Type",
    'x-verify': "6ab24e24ae92646c82e0450f029478117d8a1a0a00390e266ea1178a0c68e419###1"
    }

response = requests.request("GET", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "success": true,/* Rely on success flag and
   code parameter as PAYMENT_SUCCESS for 
   successful transaction */
  
  "code": "PAYMENT_SUCCESS",
  "message": "Your payment is successful.",
  "data": {
    "transactionId": "TX123456789",
    "merchantId": "U123456789",
    "amount": 100,
    "providerReferenceId": "PPXXXXXX",
    "payResponseCode": "SUCCESS",
    "paymentState": "COMPLETED"/* This is an
     informative field. For making decisions
     rely on 'code' field */
  }
}
{
  "success": false,
  "code": "TRANSACTION_NOT_FOUND",
  "message": "No Transaction found with the given details.",
  "data": {}
}

Path Params

merchantId
string
required

Unique Merchant ID assigned to the merchant by PhonePe

transactionId
string
required

Merchant transaction id for which status is to be fetched

Headers

Content-Type
string
required

application/json

X-VERIFY
string
required

SHA256("/v3/transaction/{merchantId}/{transactionId}/status" + saltKey) + "###" + saltIndex

 

It is mandatory for the merchant to check the status of a transaction post callback from Accept Payments or Refund workflows.

  • Once customer is redirected back to merchant website, it is recommended to make a transaction status check with PhonePe backend systems to know the actual status of the payment and, then accordingly process the result.
  • The payment status can be Success, Failed or Pending. When Pending, merchants should retry until the status changes to Success or Failed.

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256("/v3/transaction/{merchantId}/{transactionId}/status" +
saltKey) + "###" + saltIndex

Path Parameters

Parameter Name
Type
Description
Mandatory

merchantId

STRING

Unique Merchant ID assigned to the merchant by PhonePe

Yes

transactionId

STRING

Merchant transactionID for which status is to be fetched

Yes

Response Parameters

Parameter Name
Type
Description

success

BOOLEAN

A boolean to indicate the success/failure of the request.

code

ENUM

Please see the list of Transaction Status Response Codes below. You should base your decision on this parameter.

message

STRING

Short message about status of transaction

transactionId

STRING

Unique Transaction ID generated by the merchant to track this request to PhonePe

merchantId

STRING

Unique Merchant ID assigned to the merchant by PhonePe

amount

LONG

Transaction amount in paise

providerReferenceId

STRING

PhonePe transaction Id

paymentState

STRING

Please ignore this. Use "code" parameter to get latest status of transaction.

payResponseCode

STRING

PhonePe internal status code. Please note this is a string value and new codes are likely to be added in the future. (Please don't do the marshalling/unmarshalling into an enum for this at your side). This is an informative value.

Transaction Status Response Codes

Code
Description

TRANSACTION_NOT_FOUND

Payment not initiated inside PhonePe

BAD_REQUEST

Invalid request

AUTHORIZATION_FAILED

X-VERIFY header is incorrect

INTERNAL_SERVER_ERROR

Something went wrong. Merchant needs to call Check Transaction Status to verify the transaction status.

PAYMENT_SUCCESS

Payment is successful or In case of refund - Refund is successful.

PAYMENT_ERROR

Payment failed

PAYMENT_PENDING

Payment is pending. It does not indicate failed payment. Merchant needs to call Check Transaction Status to verify the transaction status.

PAYMENT_DECLINED

Payment declined by user

PAYMENT_CANCELLED

Payment cancelled by the merchant using Cancel API

Cross-check the amount which has been passed in forward payment path(Accept payment API) and in the response of Check Transaction Status API.

Refund

API flow to refund against a payment transaction made through PhonePe. A full or partial refund is possible against a transaction.

 
posthttps://mercury-uat.phonepe.com/v3/credit/backToSource
curl --request POST \
  --url https://mercury-uat.phonepe.com/v3/credit/backToSource \
  --header 'content-type: application/json' \
  --header 'x-verify: X-VERIFY'
var request = require("request");

var options = { method: 'POST',
  url: 'https://mercury-uat.phonepe.com/v3/credit/backToSource',
  headers:
   { 'x-verify': 'X-VERIFY',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/credit/backToSource")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = 'X-VERIFY'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://mercury-uat.phonepe.com/v3/credit/backToSource");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "X-VERIFY");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/credit/backToSource"

headers = {
    'content-type': "application/json",
    'x-verify': "X-VERIFY"
    }

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
   "success": true,
   "code": "PAYMENT_SUCCESS",
   "message": "Your payment is successful.",
   "data": {
       "transactionId": "TX123456789",
       "merchantId": "DemoMerchant",
       "amount": 100,
       "status": "SUCCESS",
       "mobileNumber": "9xxxxxxxxxx",
       "providerReferenceId": "PPXXXXX",
       "payResponseCode": "SUCCESS"
   }
}
{
  "success": false,
  "code": "INVALID_TRANSACTION_ID",
  "message": "The transaction id you have entered seems to be invalid.",
  "data": {}
}

Body Params

request
string
required

base64 encoded payload

Headers

Content-type
string
required
X-VERIFY
string
required

SHA256(base64 encoded payload + "/v3/credit/backToSource" + salt key) + ### + salt index

 

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256(base64 encoded payload + "/v3/credit/backToSource" + salt key) + ### + salt index

Request Parameters

Parameter Name
Type
Description
Mandatory

merchantId

STRING

Unique Merchant ID assigned to the merchant by PhonePe

Yes

transactionId

STRING

Unique Transaction ID generated by the merchant to track this request to PhonePe.
This should be different from transaction ID of debit transaction.

Yes

originalTransactionId

STRING

Merchant transaction Id of forward transaction which needs to be reversed.

Yes

providerReferenceId

STRING

PhonePe transaction id of the original forward payment.
Note : use only one of originalTransactionId, providerReferenceId only

Yes

amount

LONG

Reversal amount in paise. Upto a max of amount of original payment transaction.

Yes

merchantOrderId

STRING

Order ID for the merchant transaction

Yes

subMerchant

STRING

Tag to categorize merchant transaction

No

message

STRING

Short message

Yes

Response Parameters

Parameter Name
Type
Description

success

BOOLEAN

Success status of the request

code

ENUM

See list of response codes below

message

STRING

Short message about code

transactionId

STRING

Unique Transaction ID generated by the merchant to track this request to PhonePe

merchantId

STRING

Unique Merchant ID assigned to the merchant by PhonePe

amount

LONG

Transaction amount in paise

status

STRING

Status of the request

mobileNumber

STRING

Mobile number of the user

providerReferenceId

STRING

PhonePe payment transaction id against which the reversal is to be done

payResponseCode

STRING

PhonePe internal status code

Refund API Response Codes

Code
Description

BAD_REQUEST

Invalid request

AUTHORIZATION_FAILED

X-VERIFY header is incorrect

TRANSACTION_NOT_FOUND

Original transaction not found

INTERNAL_SERVER_ERROR

Something went wrong. Refund might get initiated (need to check status with check transaction status API before retrying the refund)

PAYMENT_SUCCESS

Payment is successful

PAYMENT_ERROR

Payment failed

PAYMENT_PENDING

Payment is pending. It does not indicate failed payment. Refund might get initiated (need to check status with check transaction status API before retrying the refund)

TIMED_OUT

Refund timed out. Refund might get initiated (need to check status with check transaction status API before retrying the refund)

DUPLICATE_TXN_REQUEST

If the transaction id is used already for refund request.

EXCESS_REFUND_AMOUNT

If the amount requested for refund is more than forward payment or If refund is already done

WALLLET_NOT_ACTIVATED

If the user has disabled the wallet. Contact user to know the source for refund.

{
    "merchantId": "DemoMerchant",
    "transactionId": "TX123456789",
    "providerReferenceId": "PPXXXXX",
    "amount": 100,
    "merchantOrderId": "OD1234",
    "subMerchant": "DemoMerchant",
    "message": "refund for cancelled order"
}
{
  "request": "eyJtZXJjaGFudE9yZGVySWQiOiAiT0QxMjM0IiwgInN1Yk1lcmNoYW50IjogIkRlbW9NZXJjaGFudCIsICJhbW91bnQiOiAxMDAsICJtZXNzYWdlIjogInJlZnVuZCBmb3IgY2FuY2VsbGVkIG9yZGVyIiwgIm1vYmlsZU51bWJlciI6ICI5eHh4eHh4eHh4IiwgInNob3J0TmFtZSI6ICJBbWl0IiwgInRyYW5zYWN0aW9uSWQiOiAiVFgxMjM0NTY3ODkiLCAibWVyY2hhbnRVc2VySWQiOiAiVTEyMzQ1Njc4OSIsICJtZXJjaGFudElkIjogIkRlbW9NZXJjaGFudCIsICJlbWFpbCI6ICJhbWl0eHh4NzVAZ21haWwuY29tIn0"
}

Primary APIs

 


This section details the APIs you need to work with to accept payments on your app using PhonePe and for handling operational issues related to payments.

Accept Payments

 

Server Side

  1. Save the below Assigned apiEndPoint value at your server for the debit request.
String apiEndPoint = "/v4/debit";
  1. Construct the request body and encode in Base 64 at your server as follows:
HashMap<String, Object> data = new HashMap<>();
data.put("merchantId", “M2306160483220675579140”); //String. Mandatory
data.put("transactionId", “TX123456789”); //String. Mandatory. 
data.put("amount", 100); //Long. Mandatory

//Note: Don't pass this if you are passing userAuthToken.
data.put("merchantUserId", “U123456789”); //String. Mandatory. Needed for linking 

//Note : Used only for OTP linking flow.
data.put("userAuthToken", <userAuthToken>); //String. Optional. Needed for linking 

data.put("merchantOrderId", “OD1234”); //String. Mandatory
data.put("message", “Payment for order placed 001234); //String. Optional
data.put("mobileNumber", “9xxxxxxxxx”); //String. Optional
data.put("email", “amit***75@gmail.com”); //String. Optional
data.put("shortName",  “Amit”); //String. Optional
data.put("subMerchant", “DemoMerchant”); //String. ONLY if a submerchant id has been allocated to you.

//Note : Used only for Open Intent flow.
data.put("paymentScope", "ALL_UPI_APPS"); // String. Mandatory

// transactionId length should be less than 38 characters.
// merchantOrderId length should be less than 48 characters.
// Put more info as intimated. Nesting is allowed

String base64Body = Base64(new GSON().toJson(data));

Parameter Name
Type
Description
Mandatory

merchantId

STRING

Unique MerchantID assigned to the merchant by PhonePe

Yes

transactionId

STRING

Unique TransactionID generated by the merchant to track request to PhonePe
transactionId length should be less than 38 characters.

Yes

merchantUserId

STRING

Unique UserID generated by merchant. This is used to pre-login users authenticated on PhonePe. Un-authenticated users are redirected to PhonePe login page. Conversions are higher when this is provided. Avoid passing email/mobile number.
Skip this for guest users.
Note:
Don't pass this if you are passing userAuthToken.

Yes

userAuthToken

STRING

Unique userAuthTokengiven to merchant in OTP flow. This is used to pre-login users authenticated on PhonePe. If not passed users will be redirected to PhonePe login page.
Note : Used only for OTP linking flow.


amount

LONG

Transaction amount in Paise

Yes

merchantOrderId

STRING

OrderID generated by the merchant
merchantOrderId length should be less than 48 characters.

No

subMerchant

STRING

.Tag to categorize merchant transaction.
Skip this field if you don't have multiple merchants tagged under one merchant id

No

mobileNumber

STRING

Mobile number of the user

No

message

STRING

Short message. This message is displayed to the user on completion of payment.

No

email

STRING

Email address of the user

No

shortName

STRING

User's name pre-filled for registration purpose.

No

  1. Select one of the API keys shared with you and note it's index. Refer this link for salt key value and salt index credentials. Construct the checksum at your server as follows:
String checksum = sha256(base64Body + apiEndPoint + salt) + ### + saltIndex;

App Side

  1. Collect Base64 encoded payload, checksum, apiEndPoint and transactionId from your server.
  2. a. Initiate the payment process as follows:
TransactionRequest debitRequest = new TransactionRequestBuilder()
	.setData(base64Body)
	.setChecksum(checksum)
	.setUrl(apiEndPoint)
	.build();

//For Intent SDK call below fuction 

try {
    startActivityForResult(PhonePe.getTransactionIntent(/* Context */ this, debitRequest),DEBIT_REQUEST_CODE);
} catch(PhonePeInitException e){
}

//For open Intent call below function, Other flows will remain as it is.  

try {
    startActivityForResult(PhonePe.getImplicitIntent(/* Context */ this, debitRequest),DEBIT_REQUEST_CODE);
} catch(PhonePeInitException e){
}
  1. b. For server to server callback option, refer to below
Map<String, String> headers = new HashMap();
headers.put("X-CALLBACK-URL","https://www.demoMerchant.com");  // Merchant server URL
headers.put("X-CALL-MODE","POST");
headers.put("X-PROVIDER-ID","M2401563246873249082352"); // ONLY if x-provider-id has been allocated to you.
TransactionRequest debitRequest = new TransactionRequestBuilder()
	.setData(base64Body)
	.setChecksum(checksum)
	.setUrl(apiEndPoint)
	.setHeaders(headers)
	.build();

//For Intent SDK call below fuction 

try {
    startActivityForResult(PhonePe.getTransactionIntent(
    /* Context */ this, debitRequest),DEBIT_REQUEST_CODE);
} catch(PhonePeInitException e){
}

//For open Intent call below function, Other flows will remain as it is.  

try {
    startActivityForResult(PhonePe.getImplicitIntent(/* Context */ this, debitRequest),DEBIT_REQUEST_CODE);
} catch(PhonePeInitException e){
}

If you get a blank screen with "Load more", refer Troubleshooting.

  1. Override onActivityResult to listen to debit result:
private static int DEBIT_REQUEST_CODE = 777;
 
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
 
    if (requestCode == DEBIT_REQUEST_CODE) {
      
      /*This callback indicates only about completion of UI flow.
            Inform your server to make the transaction
            status call to get the status. Update your app with the
            success/failure status.*/
    }   
}
  • Inform your server about the completion of the transaction flow from your app.
  • Your server should make the Check Transaction Status API call to PhonePe server to check the transaction status(Even for RESULT_CANCELED).
  • Get the result and notify your app.
  • Based on the result inform the user about success or failure status of the transaction.

Server Side

  1. Refer to Check Transaction Status API for the server to server call to get the transaction status.
    The payment status can be Success, Failed, Pending or any of codes. For Pending, merchants should retry until the status changes to Success or Failed.
  2. Refer to Refund API for the reconciliation.
    There could be cases where amount gets deducted but you receive payment in Pending in the Check Transaction Status . For such cases either you can show order failed immediately and refund the amount when pending changes to success using Refund API or show order placed according to your use case.

Other APIs

 


These APIs are optional. Based on the nature of your business, you may choose to integrate them.

Logout and Clear Cache

 


Use the following code to logout and clear the cache.

PhonePe.logout()

Primary APIs

 

Accept Payments-1

 
posthttps://mercury-uat.phonepe.com/v4/debit
curl --request POST \
  --url https://mercury-uat.phonepe.com/v4/debit \
  --header 'content-type: application/json' \
  --header 'x-redirect-mode: X-REDIRECT-MODE' \
  --header 'x-redirect-url: X-REDIRECT-URL' \
  --header 'x-verify: X-VERIFY'
var request = require("request");

var options = { method: 'POST',
  url: 'https://mercury-uat.phonepe.com/v4/debit',
  headers:
   { 'x-redirect-mode': 'X-REDIRECT-MODE',
     'x-redirect-url': 'X-REDIRECT-URL',
     'x-verify': 'X-VERIFY',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v4/debit")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = 'X-VERIFY'
request["x-redirect-url"] = 'X-REDIRECT-URL'
request["x-redirect-mode"] = 'X-REDIRECT-MODE'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://mercury-uat.phonepe.com/v4/debit");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "X-VERIFY");
xhr.setRequestHeader("x-redirect-url", "X-REDIRECT-URL");
xhr.setRequestHeader("x-redirect-mode", "X-REDIRECT-MODE");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v4/debit"

headers = {
    'content-type': "application/json",
    'x-verify': "X-VERIFY",
    'x-redirect-url': "X-REDIRECT-URL",
    'x-redirect-mode': "X-REDIRECT-MODE"
    }

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
	"code": "SUCCESS",
	"message": "Your request has been successfully completed.",
	"data": {
		"redirectType": "INTENT",
		"redirectURL": "upi://pay? 	pn=PAYU&pa=PAYUPAYMENTS@ybl&tid=YBL6663638d0312408a8f54f7df8f1bd6b9&tr=P1812191027266848105909&am=405.00&mam=405.00&cu=INR&url=https://phonepe.com&mc=7299&tn=Payment%20for%207787496005&utm_source=7787496005&utm_medium=PAYUPAYMENTS&utm_campaign=DEBIT"
	}
}


{
  "success": false,
  "code": "INVALID_TRANSACTION_ID",
  "message": "The transaction id you have entered seems to be invalid.",
  "data": {}
}

Body Params

request
string

base64 encoded payload

Headers

Content-Type
string
required
X-VERIFY
string
required

SHA256(base64 encoded payload + "/v4/debit" + salt key) + ### + salt index

X-REDIRECT-URL
string
required

Dynamic redirect URI for UI callback

X-REDIRECT-MODE
string
required

REDIRECT/ POST

X-CALLBACK-URL
string

S2S callback url

X-CALL-MODE
string

S2S call mode (POST/ PUT)

 

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256(base64 encoded payload + "/v4/debit" + salt key) + ### + salt index

X-REDIRECT-URL

Dynamic redirect URI for UI callback

X-REDIRECT-MODE

REDIRECT/ POST

X-CALLBACK-URL

S2S callback url

X-CALL-MODE

S2S call mode (POST/ PUT)

Request Parameters

Parameter Name

Type

Description

Mandatory

merchantId

STRING

Unique MerchantID assigned to the merchant by PhonePe

Yes

transactionId

STRING

Unique TransactionID generated by the merchant to track request to PhonePe
transactionId length should be less than 38 characters.

Yes

merchantUserId

STRING

Unique UserID generated by merchant. This is used to pre-login users authenticated on PhonePe. Un-authenticated users are redirected to PhonePe login page. Conversions are higher when this is provided. Avoid passing email/mobile number.
Skip this for guest users.
Note:
Don't pass this if you are passing userAuthToken.

Yes

userAuthToken

STRING

Unique userAuthTokengiven to merchant in OTP flow. This is used to pre-login users authenticated on PhonePe. If not passed users will be redirected to PhonePe login page.
Note : Used only for OTP linking flow.

Only for OTP linking flow.

amount

LONG

Transaction amount in Paise

Yes

merchantOrderId

STRING

OrderID generated by the merchant
merchantOrderId length should be less than 48 characters.

Yes

subMerchant

STRING

Tag to categorize merchant transaction.
Skip this field if you don't have multiple merchants tagged under one merchant id.

No

mobileNumber

STRING

Mobile number of the user

No

message

STRING

Short message. This message is displayed to the user on completion of payment.

No

email

STRING

Email address of the user

No

shortName

STRING

User's name pre-filled for registration purpose.

No

paymentScope

STRING

Value should be "PHONEPE"

Yes

deviceContext

OBJECT

PhonePe version code

Yes

merchantContext

OBJECT

No

Response Parameters

Parameter Name
Type
Description

success

BOOLEAN

Success status of the request

code

ENUM

See list of response codes below

{	
	"merchantId": "M2306160483220675579140",
	"transactionId": "e3e1mmcccdmm9ef8vdfmd7b",
	"merchantUserId": "unknown8898",
	"userAuthToken": "unknown8898",	
	"amount": 200,
	"merchantOrderId": "OD139924923",
	"subMerchant": "unknown8898",
	"mobileNumber": "unknown8898",
	"message": "Payment towards order No. OD139924923.",
	"email": "xMerchantId",
	"shortName": "OD139924923",
	"paymentScope": "PHONEPE",
	"deviceContext":{
		"phonePeVersionCode": 303391
	},
	"merchantContext": {
		"offerContext": {
			"tags ": [{
			"id": "GOLD_CATEGORY",
			"amount": 100
			}]
		}
	}
}

Accept Payments Testing

 
posthttps://mercury-uat.phonepe.com/v4/debit
curl --request POST \
  --url https://mercury-uat.phonepe.com/v4/debit \
  --header 'content-type: application/json' \
  --header 'x-verify: X-VERIFY'
var request = require("request");

var options = { method: 'POST',
  url: 'https://mercury-uat.phonepe.com/v4/debit',
  headers:
   { 'x-verify': 'X-VERIFY',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v4/debit")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = 'X-VERIFY'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://mercury-uat.phonepe.com/v4/debit");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "X-VERIFY");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v4/debit"

headers = {
    'content-type': "application/json",
    'x-verify': "X-VERIFY"
    }

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
	"code": "SUCCESS",
	"message": "Your request has been successfully completed.",
	"data": {
		"redirectType": "INTENT",
		"redirectURL": "upi://pay? 	pn=PAYU&pa=PAYUPAYMENTS@ybl&tid=YBL6663638d0312408a8f54f7df8f1bd6b9&tr=P1812191027266848105909&am=405.00&mam=405.00&cu=INR&url=https://phonepe.com&mc=7299&tn=Payment%20for%207787496005&utm_source=7787496005&utm_medium=PAYUPAYMENTS&utm_campaign=DEBIT"
	}
}


{
  "success": false,
  "code": "INVALID_TRANSACTION_ID",
  "message": "The transaction id you have entered seems to be invalid.",
  "data": {}
}

Body Params

request
string

base64 encoded payload

Headers

Content-Type
string
required
X-VERIFY
string
required

SHA256(base64 encoded payload + "/v4/debit" + salt key) + ### + salt index

X-CALLBACK-URL
string

S2S callback url

X-CALL-MODE
string

S2S call mode (POST/ PUT)

 

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256(base64 encoded payload + "/v4/debit" + salt key) + ### + salt index

X-CALLBACK-URL

S2S callback url

X-CALL-MODE

S2S call mode (POST/ PUT)

{	
	"merchantId": "M2306160483220675579140", // String Mandatory
	"transactionId": "e3e1mmcccdmm9ef8vdfmd7b", // String Mandatory
	"merchantUserId": "unknown8898", // String Mandatory - used for auto login.
	"userAuthToken": "unknown8898", // String Mandatory - used in OTP linking flow.
	"amount": 200, // long Mandatory - amount should be in paise
	"merchantOrderId": "OD139924923", // String Mandatory
	"subMerchant": "unknown8898", // String - ONLY if sub merchant id is allocated to you 
	"mobileNumber": "unknown8898", // String - mobile number of the user
	"message": "Payment towards order No. OD139924923.", // String - message will be displayed on completion of payment.
	"email": "xMerchantId", // String - email id of the user.
	"shortName": "OD139924923", // String - user name is pre filled for registration purpose.
	"paymentScope": "PHONEPE", // String Mandatory - value should be PHONEPE only
	"deviceContext":{  // Object Mandatory
		"phonePeVersionCode": 303391 // String Mandatory - returns intent URI
	},
	"merchantContext": { // Object - Only if Deep offers is allocated to you.
		"offerContext": {
			"tags ": [{
			"id": "GOLD_CATEGORY", // String Mandatory
			"amount": 200  // String Mandatory 
			}]
		}
	}
}

// transactionId length should be less than 38 characters. 
// merchantOrderId length should be less than 48 characters.

Request Parameters

Parameter Name

Type

Description

Mandatory

merchantId

STRING

Unique MerchantID assigned to the merchant by PhonePe

Yes

transactionId

STRING

Unique TransactionID generated by the merchant to track request to PhonePe
transactionId length should be less than 38 characters.

Yes

merchantUserId

STRING

Unique UserID generated by merchant. This is used to pre-login users authenticated on PhonePe. Un-authenticated users are redirected to PhonePe login page. Conversions are higher when this is provided. Avoid passing email/mobile number.
Skip this for guest users.
Note:
Don't pass this if you are passing userAuthToken.

Yes

userAuthToken

STRING

Unique userAuthTokengiven to merchant in OTP flow. This is used to pre-login users authenticated on PhonePe. If not passed users will be redirected to PhonePe login page.
Note : Used only for OTP linking flow.

Only for OTP linking flow.

amount

LONG

Transaction amount in Paise

Yes

merchantOrderId

STRING

OrderID generated by the merchant
merchantOrderId length should be less than 48 characters.

Yes

subMerchant

STRING

Tag to categorize merchant transaction.
Skip this field if you don't have multiple merchants tagged under one merchant id.

No

mobileNumber

STRING

Mobile number of the user

No

message

STRING

Short message. This message is displayed to the user on completion of payment.

No

email

STRING

Email address of the user

No

shortName

STRING

User's name pre-filled for registration purpose.

No

paymentScope

STRING

Value should be "PHONEPE"

Yes

deviceContext

OBJECT

PhonePe version code

Yes

merchantContext

OBJECT

No

Response Parameters

Parameter Name
Type
Description

success

BOOLEAN

Success status of the request

code

ENUM

See list of response codes below

Integration

 

Server Side

  1. Save the below assigned apiEndPoint value at your server for the debit request.
String apiEndPoint = "/v4/debit";

2.Collect the phonePeVersionCode from your app.

3.Call /v4/debit API. Refer this link for more details.

4.Select one of the API keys shared with you and note it's index.
Construct the checksum at your server as follows:



String checksum = sha256(base64Body + apiEndPoint + saltKey) + ### + saltKeyIndex;

5.Initiate the payment process using Accept Payments API from the server and in the response you will receive the redirectURL which needs to be passed to the app side.

App Side

1.Check whether the PhonePe app is installed or not on the user’s device.

public boolean doesPhonePeExist(Context context)
{
    PackageInfo packageInfo = null;
    long phonePeVersionCode = -1L;
    try {
        packageInfo = getPackageManager().getPackageInfo(PHONEPE_PACKAGE_NAME,PackageManager.GET_ACTIVITIES);
        phonePeVersionCode = packageInfo.versionCode;
    } catch (PackageManager.NameNotFoundException e) {
        Log.e(TAG, String.format("failed to get package info for package name = {%s}, exception message = {%s}",
                PHONEPE_PACKAGE_NAME, e.getMessage()));
    }

    if (packageInfo == null) {
        return false;
    }

    if (phonePeVersionCode > 94033) {
        return true;
    }
    return false;
}

2.If the PhonePe app is installed on the user’s device, then you need to get the PhonePe app version code and give it to your server.

3.Once the merchant app receives the redirectUrl from the server, the deep linking option would be shown where merchant has to handle both web and intent flows by using the below code:

Web flow:

WebView mWebview = new WebView(this);
mWebview.getSettings().setJavaScriptEnabled(true);
mWebview.loadUrl(redirectUrl);
setContentView(mWebview);

Note:

  • In this case, you will receive the Web url in the "redirectURL" parameter which needs to be passed to the app side and should be launched in the android web view.
  • On loading this url, merchant will be landing on the PhonePe page, where the user can complete the payment using any payment options.
  • After completion of the payment, User interface redirection will happen to merchant redirect url. In server side merchant should be passing the following headers in the /v4/debit API: X-REDIRECT-URL and X-REDIRECT-MODE.
  • Upon payment completion merchant needs to invoke javascript bridge to inform the native Android client.
  • This will be an indication that payment flow is complete and app should check the payment status with server.

Intent flow:

Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(redirectUrl));
i.setPackage(PHONEPE_PACKAGE_NAME);
startActivityForResult(i, PHONEPE_REQUEST);

Note:

  • In this case, you will receive the intent URI in the "redirectURL" parameter in the response of the Accept Payment API response.
  • On loading this url, the merchant will invoke the PhonePe app only and completes the payment.
  • Upon payment completion merchant will receive the UI callback in onActivityResult.
  • Once you receive the UI callback, It indicates that payment flow is completed then you should check the payment status with server.

Note:

  • You will get redirectURL in the response of the Accept Payment API response.
  • For pre prod environment PhonePe package name is “com.phonepe.app.preprod”.

4.Override onActivityResult to listen to debit result:

private static final int PHONEPE_REQUEST = 123;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   super.onActivityResult(requestCode, resultCode, data);
   if (requestCode == PHONEPE_REQUEST) {
     /*This callback indicates only about
          completion of flow. 
          Inform your server to make the transaction 
          status call to get the status. Update your app with the 
          success/failure status.*/
   }
}
  • Inform your server about the completion of the transaction flow from your app.
  • Your server should make the Check Transaction Status API call to PhonePe server to check the transaction status(Even for RESULT_CANCELED).
  • Get the result and notify your app.
  • Based on the result inform the user about success or failure status of the transaction.

Server Side


1. Refer to Check Transaction Status API for the server to server call to get the transaction status.
The payment status can be Success, Failed, Pending or any of codes. For Pending, merchants should retry until the status changes to Success or Failed.

2.Refer to Refund API for the reconciliation.
There could be cases where amount gets deducted but you receive payment in Pending in the Check Transaction Status. For such cases either you can show order failed immediately and refund the amount when pending changes to success using Refund API or show order placed according to your use case.

Primary APIs

 


This section details the APIs you need to work with to accept payments on your app using PhonePe and for handling operational issues related to payments.

For other APIs such as handling refunds, visit Other APIs

Accept Payment

 

Server Side

  1. Save the below Assigned apiEndPoint value at your server for the debit request.
String apiEndPoint = "/v3/debit";
  1. Construct the request body and encode in Base 64 at your server as follows:
HashMap<String, Object> data = new HashMap<>();
data.put("merchantId", “M2306160483220675579140”); //String. Mandatory
data.put("transactionId", “TX123456789”); //String. Mandatory. 
data.put("amount", 100); //Long. Mandatory

//Note: Don't pass this if you are passing userAuthToken.
data.put("merchantUserId", “U123456789”); //String. Mandatory. Needed for linking 

//Note : Used only for OTP linking flow.
data.put("userAuthToken", <userAuthToken>); //String. Optional. Needed for linking 

data.put("merchantOrderId", “OD1234”); //String. Mandatory
data.put("message", “Payment for order placed 001234); //String. Optional
data.put("mobileNumber", “9xxxxxxxxx”); //String. Optional
data.put("email", “amit***75@gmail.com”); //String. Optional
data.put("shortName",  “Amit”); //String. Optional
data.put("subMerchant", “DemoMerchant”); //String. ONLY if a submerchant id has been allocated to you.

// transactionId length should be less than 38 characters.
// merchantOrderId length should be less than 48 characters.
// Put more info as intimated. Nesting is allowed

String base64Body = Base64(new GSON().toJson(data));
  1. Select one of the API keys shared with you and note it's index. Refer this link for salt key value and salt index credentials. Construct the checksum at your server as follows:
String checksum = sha256(base64Body + apiEndPoint + salt) + ### + saltIndex;

App Side

  1. Collect Base64 encoded payload, checksum, apiEndPoint and transactionId from your server.
  2. a. Initiate the payment process as follows:
TransactionRequest debitRequest = new TransactionRequestBuilder()
	.setData(base64Body)
	.setChecksum(checksum)
	.setUrl(apiEndPoint)
	.build();

try {
    startActivityForResult(PhonePe.getTransactionIntent(/* Context */ this, debitRequest),DEBIT_REQUEST_CODE);
} catch(PhonePeInitException e){
}
  1. b. For server to server callback option, refer to below
Map<String, String> headers = new HashMap();
headers.put("X-CALLBACK-URL","https://www.demoMerchant.com");  // Merchant server URL
headers.put("X-CALL-MODE","POST");
headers.put("X-PROVIDER-ID","M2401563246873249082352"); // ONLY if x-provider-id has been allocated to you.
TransactionRequest debitRequest = new TransactionRequestBuilder()
	.setData(base64Body)
	.setChecksum(checksum)
	.setUrl(apiEndPoint)
	.setHeaders(headers)
	.build();

try {
    startActivityForResult(PhonePe.getTransactionIntent(
    /* Context */ this, debitRequest),DEBIT_REQUEST_CODE);
} catch(PhonePeInitException e){
}

If you get a blank screen with "Load more", refer Troubleshooting.

  1. Override onActivityResult to listen to debit result:
private static int DEBIT_REQUEST_CODE = 777;
 
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
 
    if (requestCode == DEBIT_REQUEST_CODE) {
      
      /*This callback indicates only about completion of UI flow.
            Inform your server to make the transaction
            status call to get the status. Update your app with the
            success/failure status.*/
    }   
}
  • Inform your server about the completion of the transaction flow from your app.
  • Your server should make the Check Transaction Status API call to PhonePe server to check the transaction status.
  • Get the result and notify your app.
  • Based on the result inform the user about success or failure status of the transaction.

Server Side

  1. Refer to Check Transaction Status API for the server to server call to get the transaction status.
    The payment status can be Success, Failed, Pending or any of codes. For Pending, merchants should retry until the status changes to Success or Failed.
  2. Refer to Refund API for the reconciliation.
    There could be cases where amount gets deducted but you receive payment in Pending in the Check Transaction Status . For such cases either you can show order failed immediately and refund the amount when pending changes to success using Refund API or show order placed according to your use case.

Other APIs

 


These APIs are optional. Based on the nature of your business, you may choose to integrate them.

  1. Fetch Account Details
  2. Logout and Clear Cache

Fetch Account Details

 


1. Construct URL as follows:

String apiEndPoint = "/v3/account/" + <merchantId> + "/" + <merchantUserId> + "/summary";
  1. Select one of the salts shared with you and note it's index. Construct the Checksum as follows:
String checksum = sha256(apiEndPoint + salt) + ### + saltIndex;
  1. Construct the Request as follows:
try {
        PhonePe.fetchPhonePeUserDetails(apiUrl, checksum, new DataListener<UserDetails>() {
            @Override
            public void onSuccess(UserDetails userDetails) {
                /* Process the info */
            }
 
            @Override
            public void onFailure(ErrorInfo error) {
                
            }
        });
} catch(PhonePeInitException e){
}

Logout and Clear Cache

 


Use the following code to logout and clear the cache.

PhonePe.logout()

Primary APIs

 


This section details the APIs you need to work with to accept payments on your app using PhonePe and for handling operational issues related to payments (eg: display balance, user details).

For other APIs such as handling refunds, visit Other APIs

Accept Payment

 

Server Side

  1. Save the below assigned value at your server
String apiEndPoint = "/v3/debit"; // Discuss with PhonePe team regarding this
  1. Construct the request body and encode in Base 64 at your server as follows:
HashMap<String, Object> data = new HashMap<>();
data.put("merchantId", <Your merchant ID>); // String. Mandatory
data.put("transactionId", <Unique transaction id>); // String. Mandatory
data.put("amount", <amount in paise>); // Integer. Mandatory

//Note: Don't pass this if you are passing userAuthToken.
data.put("merchantUserId", userId); //String. Mandatory. Needed for linking 

//Note : Used only for OTP linking flow.
data.put("userAuthToken", userId); //String. Optional. Needed for linking 

data.put("merchantOrderId", <Order Id>); // String. Optional
data.put("message", <message summarizing the transaction>); // String. Optional
 
data.put("mobileNumber", <Mobile number of the user>); // String. Optional
data.put("email", <Email of the user>); // String. Optional
data.put("shortName", <Name of the user>); // String. Optional
 
data.put("subMerchant", <submerchant ID>); // String. ONLY if a submerchant id has been allocated to you.
 
// transactionId length should be less than 38 characters.
// merchantOrderId length should be less than 48 characters.
// Put more info as intimated. Nesting is allowed
 
String base64Body = Base64(new GSON().toJson(data));
  1. Select one of the salts shared with you and note its index. Construct the Checksum at your server as follows:
String checksum = sha256(base64Body + apiEndPoint + salt) + ### + saltIndex;

App Side

  1. Collect Base64 encoded body, checksum, apiEndPoint and transactionID from your server using an API call.
  2. Initiate the payment process as follows:
var headers = [String: String]()
headers.updateValue("<Callback URL>", forKey: "X-CALLBACK-URL")
headers.updateValue("<Callback Mode>", forKey: "X-CALL-MODE")

let debitRequest = PPSTransactionRequest(
    base64EncodedBody: <#body received by your server#>,
    apiEndPoint: <#apiEndPoint received by your server#>,
    checksum: <#checksum received by your server#>,
    headers: <#headers#>)

PhonePeSDK.shared().startPhonePeTransactionRequest(
    debitRequest,
    on: self,
    animated: true) { (debitRequest, result) in
/*
Check result.successful to check if the payment flow was successful. 
This success only indicates payment flow completion and not actual transaction status. 
You need to query your server for actual transaction status.
*/

//Check result.error for checking why the payment flow failed
 
//If you get any error, refer to the iOS Merchant Integration Document section troubleshoot for the steps to debug.

}
NSMutableDictionary *headers = [[NSMutableDictionary alloc] init];
[headers setObject:@"<Callback URL>" forKey:@"X-CALLBACK-URL"];
[headers setObject:@"<Callback Mode>" forKey:@"X-CALLBACK-MODE"];

PPSTransactionRequest * debitRequest = [[PPSTransactionRequest alloc]   
  initWithBase64EncodedBody:<#body received by your server#> 
  apiEndPoint:<#apiEndPoint received by your server#>
  checksum:<#checksum received by your server#>
  headers: <#headers#>];
    
[[PhonePeSDK shared] 
  startPhonePeTransactionRequest:transactionRequest
  onViewController:self animated:YES
  completion:^(PPSTransactionRequest * request, PPSTransactionCompletionResult * result) {

//Check result.successful to check if the payment flow was successful. This success only indicates payment flow completion and not actual transaction status. You need to query your server for actual transaction status.

//Check result.error for checking why the payment flow failed
 
//If you get any error, refer to the iOS Merchant Integration Document section troubleshoot for the steps to debug.                                           

}];
  • Inform your server about the completion of the transaction flow from your app.
  • Your server should make the Check Transaction Status call to PhonePe server to check the transaction status.
  • Get the result and notify your app.
  • Based on the result inform the user about Successful or Failed status of the transaction.

Server Side

  1. Refer to Check Transaction Status API for the server to server call to get the transaction status.
    The payment status can be Successful, Failed, Pending or any of codes. For Pending, merchants should retry until the status changes to Successful or Failed .
  2. Refer to Refund API for the reconciliation.
    There could be cases where amount gets deducted but you receive payment in pending state in the status API call.

For such cases either you can show order failed immediately and refund the amount when pending changes to success using Refund or show order placed according to your use case.

Display PhonePe Profile

 

Server Side

  1. Save the below assigned value at your server
String apiEndPoint = "/v3/profile"; // Discuss with PhonePe team regarding this
  1. Construct the request body and encode in Base 64 as follows:
HashMap<String, Object> data = new HashMap<>();
data.put("merchantId", <Your merchant ID>); // Mandatory
data.put("transactionId", <Unique transaction id>); // Mandatory
data.put("merchantUserId", userId); // Mandatory. Needed for linking
 
data.put("mobileNumber", <Mobile number of the user>); // Optional
data.put("email", <Email of the user>); // Optional
data.put("shortName", <Name of the user>); // Optional
 
// Put more info as intimated. Nesting is allowed
 
String base64Body = Base64(new GSON().toJson(data));
 
  1. Select one of the salts shared with you and note its index. Construct Checksum as follows:
String checksum = sha256(base64Body + apiEndPoint + salt) + ### + saltIndex;

App Side

  1. Collect Base64 encoded body, checksum, apiEndPoint and transactionID from your server using an API call.
  2. Initiate the process to show profile as follows:
let profileRequest = PPSTransactionRequest(
    base64EncodedBody: <#body received by your server#>,     
    apiEndPoint: <#apiEndPoint received by your server#>,
    checksum: <#checksum received by your server#>)
 
PhonePeSDK.shared().startPhonePeTransactionRequest(profileRequest,
    on: self, animated: true) { 
    (request, result) in 
    //Do something with the request/result
}
//If you get any error, refer to the iOS Merchant Integration Document section troubleshoot for the steps to debug.
PPSTransactionRequest * profileRequest = [[PPSTransactionRequest alloc]   
    initWithBase64EncodedBody:<#body received by your server#>
    apiEndPoint:<#apiEndPoint received by your server#>
    checksum:<#checksum received by your server#>];
 
[[PhonePeSDK shared] startPhonePeTransactionRequest:profileRequest
                     onViewController:self animated:YES
                     completion:^(PPSTransactionRequest * request, PPSTransactionCompletionResult * result) {
//Do something with request/result
}];
//If you get any error, refer to the iOS Merchant Integration Document section troubleshoot for the steps to debug.

Other APIs

 


These APIs are optional. Based on the nature of your business, you may choose to integrate them.

  1. Fetch Account Details
  2. Logout and Clear Cache

Fetch Account Details

 


You might want to implement this if you to determine if a user (with a merchantUserId) is on PhonePe or not.

  1. Construct the URL as follows:
String apiUrl = "/v3/account/" + <merchantId> + "/" + <merchantUserId> + "/summary";
  1. Select one of the salts shared with you and note it's index. Construct the Checksum as follows:
String checksum = sha256(apiEndPoint + salt) + ### + saltIndex;
  1. Construct the request as follows:
let request = PPSFetchUserDetailsRequest(
  apiEndPoint: <#API-End point received by your server#>, 
  checksum: <#Checksum received by your server#>)
 
PhonePeSDK.shared().fetchUserDetails(for: request) { (originalRequest, result) in
    //Determine whether or not the merchant specific user is on PhonePe
    if result.isUserOnPhonePe {
    
    }
}     
PPSFetchUserDetailsRequest *request = [[PPSFetchUserDetailsRequest alloc]    
     initWithApiEndPoint:<#API-End point received by your server#> 
     checksum:<#Checksum received by your server#>];
 
[[PhonePeSDK shared] fetchUserDetailsForRequest:request completion:^(PPSFetchUserDetailsRequest * originalRequest,
    PPSFetchUserDetailsResult * result) {
    //Determine whether or not the merchant specific user is on PhonePe
    if (result.isUserOnPhonePe) {
        
    }
}];

Logout and Clear Cache

 


Use the following code to logout and clear the cache.

PhonePeSDK.shared().logout()
[[PhonePeSDK shared] logout];

Primary APIs

 


This section details the APIs you need to work with to accept payments on your offline integration using PhonePe and for handling operational issues related to payments (eg: cancel, refund,etc.).

Request Payment

Request Payment APIs are used when the merchant wants to send a collect payment request to user's PhonePe app against an order.

 
posthttps://mercury-uat.phonepe.com/v3/charge
curl --request POST \
  --url https://mercury-uat.phonepe.com/v3/charge \
  --header 'content-type: application/json' \
  --header 'x-callback-url: X-CALLBACK-URL' \
  --header 'x-verify: X-VERIFY'
var request = require("request");

var options = { method: 'POST',
  url: 'https://mercury-uat.phonepe.com/v3/charge',
  headers:
   { 'x-callback-url': 'X-CALLBACK-URL',
     'x-verify': 'X-VERIFY',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/charge")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = 'X-VERIFY'
request["x-callback-url"] = 'X-CALLBACK-URL'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://mercury-uat.phonepe.com/v3/charge");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "X-VERIFY");
xhr.setRequestHeader("x-callback-url", "X-CALLBACK-URL");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/charge"

headers = {
    'content-type': "application/json",
    'x-verify': "X-VERIFY",
    'x-callback-url': "X-CALLBACK-URL"
    }

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "success": true,
    "code": "SUCCESS",
    "message": "Your request has been successfully completed.",
    "data":{
        "transactionId": "TX123456789",
        "amount": 100,
        "merchantId": "DemoMerchant",
        "mobileNumber": "9xxxxxxxxxx",
        "providerReferenceId": "C161XXXXXXXXXX2210"
    }
}
{
  "success": false,
  "code": "INTERNAL_SERVER_ERROR",
  "message": "There was some error with the request. Please try again.",
  "data": {}
}

Body Params

request
string
required

base64 encoded payload

Headers

Content-Type
string
required
X-VERIFY
string
required

SHA256(base64 encoded payload + "/v3/charge" + salt key) + ### + salt index

X-CALLBACK-URL
string
required

Callback Url where a request will be made once user responds to collect request.

 

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256(base64 encoded payload +
"/v3/charge" + salt key) + ### + salt index

X-CALLBACK-URL

Callback Url where a request will be made once user responds
to collect request.
Click here to see about this request.

{  
   "merchantId":"DemoMerchant",
   "transactionId":"TX123456789",
   "merchantOrderId":"M123456789",
   "amount":100,
   "instrumentType":"MOBILE",
   "instrumentReference":"9xxxxxxxxxx",
   "message":"collect for XXX order",
   "email":"amitxxx75@gmail.com",
   "expiresIn":180,
   "shortName":"DemoCustomer",
   "subMerchant":"DemoMerchant",
   "storeId":"store1",
   "terminalId":"terminal1"
}
{
  "request": "eyJtZXJjaGFudE9yZGVySWQiOiAiT0QxMjM0IiwgInN1Yk1lcmNoYW50IjogIkRlbW9NZXJjaGFudCIsICJhbW91bnQiOiAxMDAsICJtZXNzYWdlIjogInJlZnVuZCBmb3IgY2FuY2VsbGVkIG9yZGVyIiwgIm1vYmlsZU51bWJlciI6ICI5eHh4eHh4eHh4IiwgInNob3J0TmFtZSI6ICJBbWl0IiwgInRyYW5zYWN0aW9uSWQiOiAiVFgxMjM0NTY3ODkiLCAibWVyY2hhbnRVc2VySWQiOiAiVTEyMzQ1Njc4OSIsICJtZXJjaGFudElkIjogIkRlbW9NZXJjaGFudCIsICJlbWFpbCI6ICJhbWl0eHh4NzVAZ21haWwuY29tIn0"
}

Request Parameters

Parameter Name
Type
Description
Mandatory

merchantId

String

Unique Merchant ID assigned to the merchant by PhonePe

Yes

transactionId

String

Unique Transaction ID generated by the merchant to track this request to PhonePe
transactionId length
Should be unique for each collect request.
should be less than 38 characters.

Yes

merchantOrderId

String

Unique Order ID generated by the merchant
merchantOrderId length should be less than 48 characters.

Yes

amount

Long

Amount in Paisa

Yes

instrumentType

ENUM

Has the value MOBILE

Yes

instrumentReference

String

Mobile number of the user

Yes

expiresIn

Long

expire time of payment completion.Payment should be completed with in this time else will be markedfailed. (default 30 days)

Yes

message

String

Recommended to pass transaction id, order id and invoice number.

No

email

String

Email Id of User

No

shortName

String

Customer Name

No

subMerchant

String

Sub-category of the merchant

No

storeId

String

Store Id of store. Should be unique across.

Yes

terminalId

String

Terminal Id of store. Should be unique for a store.

Yes

Response Parameters

Parameter Name
Type
Description

success

BOOLEAN

Success status of the request

code

ENUM

See below section for list of codes

message

STRING

Short message about status of request

transactionId

STRING

Unique Transaction ID generated by the merchant to track this request to PhonePe

merchantId

STRING

Unique Merchant ID assigned to the merchant by PhonePe

amount

LONG

Transaction amount in paise

providerReferenceId

STRING

PhonePe transaction Id

mobileNumber

STRING

Mobile Number

Response Codes

The code in the above API response could be:

  • SUCCESS : Collect was successfully sent to VPA
  • INTERNAL_SERVER_ERROR : Something went wrong. Need to validate through check transaction status API first to know the payment status.
  • INVALID_TRANSACTION_ID : TransactionId in request was duplicate
  • BAD_REQUEST : Some mandatory parameter was missing
  • AUTHORIZATION_FAILED : Checksum sent in header was not valid

Charge Callback

When the user responds to the collect request sent by the merchant, a request is sent to either the URL provided in X-CALLBACK-URL or the merchant's registered callback URL. By default, this is a PUT request.

Note:

  • The callback would be sent only for success/Failed scenarios. For pending cases, there won't be any callback. For such transactions payment status should be checked with below API.
  • If payment is in pending state, Merchant should display a message "Payment is in progress, please wait for sometime."
  • The payment will always be closed within the expiry time passed in the collect request.

Check Payment Status

Used to check the status of the payment request.

Status against a particular MerchantId:TransactionId can be fetched using the transaction status API. Please refer below section for details.

 
gethttps://mercury-uat.phonepe.com/v3/transaction/merchantId/transactionId/status
curl --request GET \
  --url https://mercury-uat.phonepe.com/v3/transaction/M2306160483220675579140/1511522079/status \
  --header 'content-type: application/json' \
  --header 'x-verify: 6ab24e24ae92646c82e0450f029478117d8a1a0a00390e266ea1178a0c68e419###1'
var request = require("request");

var options = { method: 'GET',
  url:
   'https://mercury-uat.phonepe.com/v3/transaction/M2306160483220675579140/1511522079/status',
  headers:
   { 'x-verify':
      '6ab24e24ae92646c82e0450f029478117d8a1a0a00390e266ea1178a0c68e419###1',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/transaction/M2306160483220675579140/1511522079/status")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = '6ab24e24ae92646c82e0450f029478117d8a1a0a00390e266ea1178a0c68e419###1'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://mercury-uat.phonepe.com/v3/transaction/M2306160483220675579140/1511522079/status");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "6ab24e24ae92646c82e0450f029478117d8a1a0a00390e266ea1178a0c68e419###1");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/transaction/M2306160483220675579140/1511522079/status"

headers = {
    'content-type': "application/json",
    'x-verify': "6ab24e24ae92646c82e0450f029478117d8a1a0a00390e266ea1178a0c68e419###1"
    }

response = requests.request("GET", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
       "success": true,
       "code": "PAYMENT_SUCCESS",
       "message": "Your payment is successful.",
       "data": {
           "transactionId": "TX123456789",
           "merchantId": "U123456789",
           "amount": 100,
           "providerReferenceId": "PPXXXXXX",
           "paymentState": "COMPLETED",
           "payResponseCode": "SUCCESS"
       }
  }
{
  "success": false,
  "code": "TRANSACTION_NOT_FOUND",
  "message": "No Transaction found with the given details.",
  "data": {}
}

Path Params

merchantId
string
required

Unique Merchant ID assigned to the merchant by PhonePe

transactionId
string
required

Merchant transaction id for which status is to be fetched

Headers

Content-Type
string
required
X-VERIFY
string
required

SHA256("/v3/transaction/{merchantId}/{transactionId}/status" + saltKey) + "###" + saltIndex

 

It is mandatory for the merchant to check the status of a transaction.

  • The cashier should select the "check the transaction status" button which should call the terminal's server. Terminal's server should call PhonePe server with this API to know the status.
  • Add a message in the POS asking the cashier to click the Check Status button only after customer tells the cashier that he has made the payment.
  • The payment status can be Success, Failed or Pending.
  • When Pending, There should be a message POS "Payment is in progress, please check the status after sometime." (ideally, Collect expiry time - current time taken). "
  • For eg. let's assume the expiry time passed in collect request is 180 sec. Status is checked after 60 sec and payment is in pending state, the time to wait will 120 sec maximum since payment will be closed within 180 sec.

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256("/v3/transaction/{merchantId}/{transactionId}/status" +
saltKey) + "###" + saltIndex

Path Parameters

Parameter Name
Type
Description
Mandatory

merchantId

STRING

Unique Merchant ID assigned to the merchant by PhonePe

Yes

transactionId

STRING

Merchant transactionID for which status is to be fetched

Yes

Response Parameters

Parameter Name
Type
Description

success

BOOLEAN

A boolean to indicate the success/failure of the request.

code

ENUM

Please see the list of Transaction Status Response Codes below. You should base your decision on this parameter.

message

STRING

Short message about status of transaction

transactionId

STRING

Unique Transaction ID generated by the merchant to track this request to PhonePe

merchantId

STRING

Unique Merchant ID assigned to the merchant by PhonePe

amount

LONG

Transaction amount in paise

providerReferenceId

STRING

PhonePe transaction Id

paymentState

ENUM

Transaction Status, Refer below section for list of states

payResponseCode

STRING

PhonePe internal status code. Please note this is a string value and new codes are likely to be added in the future. (Please don't do the marshalling/unmarshalling into an enum for this at your side). This is an informative value.

Transaction Status Response Codes

Code
Description

TRANSACTION_NOT_FOUND

Payment not initiated inside PhonePe

BAD_REQUEST

Invalid request

AUTHORIZATION_FAILED

X-VERIFY header is incorrect

INTERNAL_SERVER_ERROR

Something went wrong

PAYMENT_SUCCESS

Payment is successful

PAYMENT_ERROR

Payment failed

PAYMENT_PENDING

Payment is pending. It does not indicate failed payment.

PAYMENT_CANCELLED

Payment cancelled by merchant

PAYMENT_DECLINED

Payment declined by user

Cross-check the amount which has been passed in forward payment path(Accept payment API) and in the response of Check Transaction Status API.

Cancel Payment Request

Used to cancel the collect request

 
posthttps://mercury-uat.phonepe.com/v3/charge/merchantId/transactionId/cancel
curl --request POST \
  --url https://mercury-uat.phonepe.com/v3/charge/merchantId/transactionId/cancel \
  --header 'content-type: application/json' \
  --header 'x-verify: X-VERIFY'
var request = require("request");

var options = { method: 'POST',
  url:
   'https://mercury-uat.phonepe.com/v3/charge/merchantId/transactionId/cancel',
  headers:
   { 'x-verify': 'X-VERIFY',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/charge/merchantId/transactionId/cancel")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = 'X-VERIFY'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://mercury-uat.phonepe.com/v3/charge/merchantId/transactionId/cancel");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "X-VERIFY");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/charge/merchantId/transactionId/cancel"

headers = {
    'content-type': "application/json",
    'x-verify': "X-VERIFY"
    }

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "success": true,
    "code": "SUCCESS",
    "message":"Your request has been successfully completed.",
    "data":{}
}

Path Params

merchantId
string
required

Unique Merchant ID assigned to the merchant by PhonePe

transactionId
string
required

Unique Transaction ID generated by the merchant to track this request to PhonePe

Headers

Content-Type
string
required
X-VERIFY
string
required

SHA256("/v3/charge/{merchantId}/{transactionId}/cancel" + salt key) + ### + salt index

 

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256("/v3/charge/{merchantId}/{transactionId}/cancel" +
salt key) + ### + salt index

Path Parameters

Parameter Name
Type
Description
Mandatory

merchantId

STRING

Unique Merchant ID assigned to the merchant by PhonePe

Yes

transactionId

STRING

Unique Transaction ID generated by the merchant to track this request to PhonePe

Yes

Response Parameters

Parameter Name
Type
Description

success

BOOLEAN

Success status of the request

code

ENUM

See below section for list of codes

message

STRING

Short message about status

data

OBJECT

Empty object

Response Codes

The code in the above API response could be.

  • SUCCESS
  • INTERNAL_SERVER_ERROR : There can be internal server error. Merchant should retry the cancel API request.
  • INVALID_TRANSACTION_ID
  • PAYMENT_ALREADY_COMPLETED : Payment has been succesful hence can't cancel the request. For this case merchant should trigger successful transaction, generating the bill.

Remind Payment Request

Used to send the reminder for payment request.

 
posthttps://mercury-uat.phonepe.com/v3/charge/merchantId/transactionId/remind
curl --request POST \
  --url https://mercury-uat.phonepe.com/v3/charge/merchantId/transactionId/remind \
  --header 'content-type: application/json' \
  --header 'x-verify: X-VERIFY'
var request = require("request");

var options = { method: 'POST',
  url:
   'https://mercury-uat.phonepe.com/v3/charge/merchantId/transactionId/remind',
  headers:
   { 'x-verify': 'X-VERIFY',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/charge/merchantId/transactionId/remind")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = 'X-VERIFY'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://mercury-uat.phonepe.com/v3/charge/merchantId/transactionId/remind");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "X-VERIFY");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/charge/merchantId/transactionId/remind"

headers = {
    'content-type': "application/json",
    'x-verify': "X-VERIFY"
    }

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "success": true,
    "code": "SUCCESS"
}

Path Params

merchantId
string
required

Unique Merchant ID assigned to the merchant by PhonePe

transactionId
string
required

Unique Transaction ID generated by the merchant to track this request to PhonePe

Headers

Content-Type
string
required
X-VERIFY
string
required

SHA256("/v3/charge/{merchantId}/{transactionId}/remind" + salt key) + ### + salt index

 

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256("/v3/charge/{merchantId}/{transactionId}/remind" +
salt key) + ### + salt index

Path Parameters

Parameter Name
Type
Description
Mandatory

merchantId

STRING

Unique Merchant ID assigned to the merchant by PhonePe

Yes

transactionId

STRING

Unique Transaction ID generated by the merchant to track this request to PhonePe

Yes

Response Parameters

Parameter Name
Type
Description

success

BOOLEAN

Success status of the request

code

ENUM

See below section for list of codes

Response Codes

The code in the above API response could be.

  • SUCCESS
  • INTERNAL_SERVER_ERROR
  • INVALID_TRANSACTION_ID

Refund

API flow to refund against a payment transaction made through PhonePe. A full or partial refund is possible against a transaction.

 
posthttps://mercury-uat.phonepe.com/v3/credit/backToSource
curl --request POST \
  --url https://mercury-uat.phonepe.com/v3/credit/backToSource \
  --header 'content-type: application/json' \
  --header 'x-verify: X-VERIFY'
var request = require("request");

var options = { method: 'POST',
  url: 'https://mercury-uat.phonepe.com/v3/credit/backToSource',
  headers:
   { 'x-verify': 'X-VERIFY',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/credit/backToSource")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'
request["x-verify"] = 'X-VERIFY'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://mercury-uat.phonepe.com/v3/credit/backToSource");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-verify", "X-VERIFY");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/credit/backToSource"

headers = {
    'content-type': "application/json",
    'x-verify': "X-VERIFY"
    }

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
   "success": true,
   "code": "PAYMENT_SUCCESS",
   "message": "Your payment is successful.",
   "data": {
       "transactionId": "TX123456789",
       "merchantId": "DemoMerchant",
       "amount": 100,
       "status": "SUCCESS",
       "mobileNumber": "9xxxxxxxxxx",
       "providerReferenceId": "PPXXXXX",
       "payResponseCode": "SUCCESS"
   }
}
{
  "success": false,
  "code": "INVALID_TRANSACTION_ID",
  "message": "The transaction id you have entered seems to be invalid.",
  "data": {}
}

Body Params

request
string
required

base64 encoded payload

Headers

Content-type
string
required
X-VERIFY
string
required

SHA256(base64 encoded payload + "/v3/credit/backToSource" + salt key) + ### + salt index

 

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256(base64 encoded payload + "/v3/credit/backToSource" + salt key) + ### + salt index

Request Parameters

Parameter Name
Type
Description
Mandatory

merchantId

STRING

Unique Merchant ID assigned to the merchant by PhonePe

Yes

transactionId

STRING

Unique Transaction ID generated by the merchant to track this request to PhonePe

Yes

providerReferenceId

STRING

PhonePe transaction Id of previous transaction which needs to be reversed.

Yes

amount

LONG

Reversal amount in paise. Upto a max of amount of original payment transaction.

Yes

merchantOrderId

STRING

Order ID for the merchant transaction

Yes

subMerchant

STRING

Tag to categorize merchant transaction

No

message

STRING

Short message

Yes

Response Parameters

Parameter Name
Type
Description

merchantId

BOOLEAN

Success status of the request

code

ENUM

To see list of response codes go here.

message

STRING

Short message about code

transactionId

STRING

Unique Transaction ID generated by the merchant to track this request to PhonePe

merchantId

STRING

Unique Merchant ID assigned to the merchant by PhonePe

amount

LONG

Transaction amount in paise

status

STRING

Status of the request

mobileNumber

STRING

Mobile number of the user

providerReferenceId

STRING

PhonePe payment transaction id against which the reversal is to be done

payResponseCode

STRING

PhonePe internal status code

{
    "merchantId": "DemoMerchant",
    "transactionId": "TX123456789",
    "providerReferenceId": "PPXXXXX",
    "amount": 100,
    "merchantOrderId": "OD1234",
    "subMerchant": "DemoMerchant",
    "message": "refund for cancelled order"
}
{
  "request": "eyJtZXJjaGFudE9yZGVySWQiOiAiT0QxMjM0IiwgInN1Yk1lcmNoYW50IjogIkRlbW9NZXJjaGFudCIsICJhbW91bnQiOiAxMDAsICJtZXNzYWdlIjogInJlZnVuZCBmb3IgY2FuY2VsbGVkIG9yZGVyIiwgIm1vYmlsZU51bWJlciI6ICI5eHh4eHh4eHh4IiwgInNob3J0TmFtZSI6ICJBbWl0IiwgInRyYW5zYWN0aW9uSWQiOiAiVFgxMjM0NTY3ODkiLCAibWVyY2hhbnRVc2VySWQiOiAiVTEyMzQ1Njc4OSIsICJtZXJjaGFudElkIjogIkRlbW9NZXJjaGFudCIsICJlbWFpbCI6ICJhbWl0eHh4NzVAZ21haWwuY29tIn0"
}

Primary APIs

 

QR Init

QR Init is used when the merchant wants to generate a new dynamic QR code.

 
posthttps://mercury-uat.phonepe.com/v3/qr/init
curl --request POST \
  --url https://mercury-uat.phonepe.com/v3/qr/init \
  --header 'x-callback-url: X-CALLBACK-URL' \
  --header 'x-verify: X-VERIFY'
var request = require("request");

var options = { method: 'POST',
  url: 'https://mercury-uat.phonepe.com/v3/qr/init',
  headers:
   { 'x-callback-url': 'X-CALLBACK-URL',
     'x-verify': 'X-VERIFY' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://mercury-uat.phonepe.com/v3/qr/init")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["x-verify"] = 'X-VERIFY'
request["x-callback-url"] = 'X-CALLBACK-URL'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://mercury-uat.phonepe.com/v3/qr/init");
xhr.setRequestHeader("x-verify", "X-VERIFY");
xhr.setRequestHeader("x-callback-url", "X-CALLBACK-URL");

xhr.send(data);
import requests

url = "https://mercury-uat.phonepe.com/v3/qr/init"

headers = {
    'x-verify': "X-VERIFY",
    'x-callback-url': "X-CALLBACK-URL"
    }

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

Try the API to see results

Body Params

request
string
required

base64 encoded payload

Headers

X-VERIFY
string
required

SHA256(base64 encoded payload + "/v3/qr/init" + salt key) + ### + salt index

X-CALL-MODE
string

HTTP mode to be used for UI callback. Default Values are POST/PUT.

X-CALLBACK-URL
string
required

Dynamic callback URI for server to server callback

Content-Type
string
 

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256(base64 encoded payload + "/v3/qr/init" +
salt key) + ### + salt index

X-CALLBACK-URL

URL on which server to server response is required
once payment is done

X-CALL-MODE

HTTP mode to be used for callback. Default Value: POST/PUT

Request Parameters

Parameter Name
Type
Description
Mandatory

merchantId

STRING

Unique MerchantID assigned to the merchant by PhonePe

Yes

subMerchantId

STRING

Unique identity of end merchant

No

storeId

STRING

Same as subMerchantId

Yes

terminalId

STRING

Unique terminal Id for each POS device

Yes

transactionId

STRING

Unique transactionId

Yes

amount

LONG

Amount in Paise

Yes

expiresIn

LONG

Expiry time in seconds

Yes

merchantOrderId

STRING

OrderId. This can be same as transactionId

No

message

STRING

Message for customer

No

Response Codes

Code
Description

INVALID_TRANSACTION_ID

Duplicate TransactionID

BAD_REQUEST

Invalid request payload

AUTHORIZATION_FAILED

Incorrect X-VERIFY header

INTERNAL_SERVER_ERROR

Something went wrong

SUCCESS

API successful

{
  "request": "ewoJIm1lcmNoYW50SWQiOiJNMjMwNjE2MDQ4MzIyMDY3NTU3OTE0MCIsCgkidHJhbnNhY3Rpb25JZCI6IlRYMzIzMjE4NDk2NDQyMzQiLAoJImFtb3VudCI6MTAwMCwKCSJzdG9yZUlkIjoiMjM0NTU1IiwKCSJ0ZXJtaW5hbElkIjoiODk0MjM3Igp9"
}
{
    "success": true,
    "code": "SUCCESS",
    "message": "Your request has been successfully completed.",
    "data": {
        "merchantId": "M2306160483220675579140",
        "transactionId": "TX32321849644234",
        "amount": 1000,
        "qrString": "upi://pay?pn=MERCHANT&pa=M2306160483220675579140@ybl&tid=YBL60c7891e33cb42daaf86b0aeb992a8b9&tr=P1806151323093900554957&am=10.00&cu=INR&url=https://phonepe.com&mc=5311&tn=Payment%20for%20P1806151323093900554957"
    }
}

Server to Server Callback

 


Once transaction is successful, we do a POST/PUT call on the URL available in request header.

Response will be base64Encoded string with checksum in header. Client is expected to validate checksum before processing the response. For more details about callback visit here.

Status Check

 


For more information about status check API refer here

Refund

 


For more information about refund API refer here

Primary APIs

 


This section details the APIs you need to work with to accept payments on your in-app integration using PhonePe.

Installation

 


To install PhonePe's Javascript SDK for your PWA/M-Site integration, please download the javascript file from this link.

Enable Logging

 

To enable logging while debugging the SDK, please set the property on PhonePe's global variable like so:

PhonePe.PhonePe.loggingEnabled = true

Create PhonePe Instance

 

build

(species: string): Promise<PhonePe>
Description: This method is used to create an instance of PhonePe. This method runs asynchronously and it is very fast. This instance is used for any calls to PhonePe's bridges.

Older build() call is deprecated

Starting JS SDK version 0.3.6 and above, the operatingSystem parameter is not needed. On SDK version < 0.3.6, operatingSystem is necessary and can be either PhonePe.Constants.OS.ios or PhonePe.Constants.OS.android. Please use the latest SDK version.

Request Parameter

Parameter Name
Type
Description

species

string

Describes if the merchant is using the sdk for web or react native.
Can be either PhonePe.Constants.Species.native or PhonePe.Constants.Species.web

Response Parameter

Promise<PhonePe>

Usage:

PhonePe.PhonePe.build(PhonePe.Constants.Species.web)
  .then((sdk) => { //Get the instance of the sdk })

OR 

let sdk = await PhonePe.PhonePe.build(PhonePe.Constants.Species.web)

isMethodSupported

(methodName: string): boolean
Description: Call this method to check if the method that you're trying to call is supported. This is a synchronous call and returns the result immediately. Methods might be added/removed and it's important to know if a method is supported by the current PhonePe app that merchant's web app is running on. Case in point, if a method gets added to the SDK, older PhonePe apps might not support the method.

For the current version of PhonePe's SDK, merchants won't need to call this.

Request Parameter

Parameter Name
Type
Description

methodName

string

Name of the method that you'd be calling

Response Parameter

boolean

Usage:

//When invoking method named setItem
if (sdk.isMethodSupported(setItem)) { sdk.setItem('app', 'key', 'value') }

Show Payments Page

 

openPaymentsPage

(merchantName: string, context: object, fallbackURL: string, imageURL: undefined/string, orderedMetaData: undefined/object): Promise<any>
Description: This method needs to be called on an instance of the sdk to open PhonePe's payments page.

Request Parameters

Parameter Name
Type
Description

merchantName

string

Name of the merchant. This will be displayed in the PhonePe's payments page.

context

object

Value of the data key in the response object sent by PhonePe server's service initiate() call Initiate Service Request

fallbackURL

string

URL to redirect after PhonePe payments flow completion, in case the webview activity gets killed (android)

imageURL

undefined/string

URL for an image that reflects the merchant's logo

orderedMetaData

Array<[string: string]> or undefined

This data is shown in the PhonePe's payments screen as an array of key-value pairs

Usage:

//Dummy information
let merchantName = "DummyMerchant"
let fallbackURL