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 + "/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.

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

 
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="
}

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.

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 = "/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.

//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) {
      
      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(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 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) {
       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.

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

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 = "https://dummymerchant.payment.com"
let imageURL = "https://image.dummymerchant.com"

//Any metadata to show on PhonePe's payment screen
//Array of key-value pairs
let orderedMetadata = [{
    "Movie": "Avengers"
}, 
{
"Seats": "3E, 4E, 5E"
}]

//Context usually looks like this
//{"merchantId":"YOUR_MERCHANT_ID","merchantTransactionId":"1234","reservationId":"1234","serviceCategory":"WEB","validFor":180,"payableAmount":100,"quantity":1}
//It's the value for the "data" key in the response object sent by PhonePe's server

sdk.openPaymentsPage(merchantName, context, fallbackURL, imageURL, orderedMetadata).then((response) => {
	console.log("Payment was successful = " + response)
}).catch((err) => {
	console.log("Payment failed with error = " + err)
})

Response Parameters

Promise<any> - The promise rejection reasons can be as follows:

Code
Description

PAYMENT_DISMISS

User pressed back button on the payments screen

PAYMENT_TIMEOUT

When the payment timed out based on the timeout interval sent by merchant to PhonePe's server in the payment initiate server call

PARAMS_INVALID_OR_INSUFFICIENT

Insufficient Parameters sent.

INTERNAL_ERROR

PhonePe's Internal error

Promise resolve:
{}

Promise reject:
{
  'error_code': 'PAYMENT_DISMISS/PAYMENT_TIMEOUT'
}

openPaymentsPageForReservedOrder

 

openPaymentsPageForReservedOrder

(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 initiate payment for a reservation (corresponding to a serviceRequestId).

Request Parameters

Parameter Name
Type
Description

merchantName

string

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

context

object

The response needs to be send which came from reserve payment() method

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
// Replace this with the response from /v3/txn/reserve API used for reservation
let context = {
"merchantId": "MERCHANTTEST",
"merchantTransactionId": "789hsaduias",
"reservationId": "W1812270939598916034792",
"serviceRequestId": "O1812270938160766034101",
"serviceCategory": "RENTAL",
"validFor": 86400,
"payableAmount": 3000,
"quantity": 1
}

/Any metadata to show on PhonePe's payment screen
//Array of key-value pairs
let orderedMetadata = [{
    "Movie": "Avengers"
}, 
{
"Seats": "3E, 4E, 5E"
}]

sdk.openPaymentsPageForReservedOrder(merchantName, context, "", "", metadata).then((response) => {
console.log("Payment was successful = " + response)
}).catch((err) => {
console.log("Payment failed with error = " + err)
})
})

Response Parameters

Promise<any> - The promise rejection reasons can be as follows:

Code
Description

PAYMENT_DISMISS

User pressed back button on the payments screen

PAYMENT_TIMEOUT

When the payment timed out based on the timeout interval sent by merchant to PhonePe's server in the payment initiate server call

PARAMS_INVALID_OR_INSUFFICIENT

Insufficient Parameters sent.

INTERNAL_ERROR

PhonePe's Internal error

Promise resolve:
{}

Promise reject:
{
  'error_code': 'PAYMENT_DISMISS/PAYMENT_TIMEOUT'
}

Ask for Permissions

 


(listOfPermissions: string[]): Promise<any>
Description: This method is used to ask for permissions for

  • Accessing User Location
  • Reading SMS (Android only)

Request Parameter

Parameter Name
Type
Description

listOfPermissions

Array<string>

List of the permissions that you would like to ask for. The permissions you can ask for are described in the table below.

Response Parameters

Promise<any>

Permission Name
Description

READ_SMS (accessed as
PhonePe.Constants.Permission. READ_SMS)

Read the user SMS​ for functionalities like OTP detection. Only available for Android.

LOCATION (accessed as
PhonePe.Constants.Permission.LOCATION)

Retrieve the user's location.

CAMERA (accessed as
PhonePe.Constants.Permission.CAMERA)

Asks for camera permission

Usage:

let result = await sdk.seekPermission([PhonePe.Constants.Permission.READ_SMS, PhonePe.Constants.Permission.LOCATION,PhonePe.Constants.Permission.CAMERA])
Promise resolve:
[  
   {  
      "permission":"LOCATION",
      "permissionGranted":true,
      "willShowPermissionAlertAgain": false
   },
   {  
      "permission":"READ_SMS",
      "permissionGranted": true,
      "willShowPermissionAlertAgain": false
   }
]

Get User Location

 

Get Current Location of the User

(): Promise<any>
Description: Call this method to get the current location of the user

Usage

//Get the location permission from PhonePe first
//See the Ask for Permissions section above to see the structure of res object
let result = await sdk.seekPermission([PhonePe.Constants.Permission.LOCATION])

//If the permission has been given for location
//Then get the current location
//Else getCurrentLocation() would reject
sdk.getCurrentLocation()
  .then((location) => { 
  	console.log("Location received with latitude = " + location.latitude + ' longitude = ' + location.longitude) 
  })
  .catch((err) => { 
  	console.log("Error found when fetching location = " + err) 
  })

Response Parameters

Promise<any>
A promise of getting the current location. Promise rejection will contain the error message if we were unable to fetch the location.

The promise rejection reason can be as follows:

Code
Description

LOCATION_FETCH_FAILURE

Unable to fetch user's location

Listening to PhonePe's User Location Updates (Special Usage)

1. Register for location update callbacks

(callbackName: string, callback: LocationResponseCallback): void

Description: Call this method to register your callback for location updates

Request Parameters

Parameter Name
Type
Description

callbackName

string

A unique name for your callback, that will help in uniquely identifying the callback

response

LocationResponseCallback = (response: any): void

A callback to register for user's location updates

Response Parameter

void

Usage:

sdk.registerLocationUpdateSuccessCallback('callbackName', (response) => {
  console.log('Location success response = ' + JSON.stringify(response)) 
})

 //Response
 {
	'latitude': 123.123, 
	'longitude': 345.345
 }

2. (Optional) Register for failure in updating location

(callbackName: string, callback: LocationResponseCallback): void

Description: Call this method to register your callback for location update FAILURES

Usage:

 sdk.registerLocationUpdateFailureCallback('callbackName', (response) => {
   console.log('Location failure response = ' + JSON.stringify(response)) 
 })
 
//Response
 {
   'error_code': 'LOCATION_UPDATE_FAILURE'
 }
   

3. Call startUpdatingLocation API to start receiving callbacks to the registered through registerLocationUpdateSuccessCallback above.

Description: This method is used get continuous location updates of the user. This is used in conjunction with @see registerLocationUpdateSuccessCallback to get notified when a user changes location. You SHOULD call stopUpdatingLocation when done as described in the next section. This helps preserve battery. For fetching location just once getCurrentLocation as stated above in the section "Get Current Location of the User"

Usage:

sdk.startUpdatingLocation()

Stop listening to PhonePe's User Location Updates (Special Usage)

Description: This method is used stop listening to location updates of the user. You should call this method if you don't need to continuously know about the user location. It's very very IMPORTANT to call this method when you would want to stop listening to the location updates. This preserves the user's battery and overall enhances the user experience.

Usage:

sdk.stopUpdatingLocation()
Promise resolve:
{
  'latitude': 123.123, 
  'longitude': 345.345
}

Promise reject:
{
  'error_code': 'LOCATION_FETCH_FAILURE'
}

Key-Value Storage

 


PhonePe provides a native persistent key-value storage. Both the keys and values can only be of type string.

getItem

(preferenceName: string, key: string, defaultValue?: undefined⎮string): Promise<string>

Description: This method is used to get a stored value from native key-value storage

Request Parameters

Parameter Name
Type
Description

preferenceName

string

Name of the key-value storage file. You can have multiple key-value storage files for your app. Should be a non-empty string.

key

string

Name of the key to fetch the value for.

defaultValue

undefined/string

Default value in case the key doesn't exist.

Usage:

sdk.getItem('app', 'key', null)
  .then((data) => {
	console.log('Value received = ' + data)
})
  .catch((err) => {})

Response Parameter

Promise<string>
A promise with the desired value or error if there is some issue. Promise failure reasons can be as follows:

Code
Description

KEY_NOT_FOUND

No value found for this key and no default value was provided


setItem

(preferenceName: string, key: string, value: string): void
Description: This method is used to store a value (string) for the corresponding key (string) into the key-value storage.

Request Parameters

Parameter Name
Type
Description

preferenceName

string

Name of the key-value storage file. You can have multiple key-value storage files for your app.

key

string

Name of the key to fetch the value for.

value

string

Value that you would like to set for the key

Response Parameter

void

Usage:

sdk.setItem('app', 'key', 'value')

removeItem

(preferenceName: string, key: string): void
Description: This method is used remove a key-value pair from key-value storage.
Usage:

sdk.removeItem('app', 'key')
Promise resolve:
'valueForKey'

Promise reject:
{
  'error_code': 'KEY_NOT_FOUND'
}

Log Merchant Event

 


(name: string, metadata: [string:string]): Promise<void>
Description: Log an event into PhonePe's ecosystem.

Parameters:

Request Parameters

Parameter Name
Type
Description

name

string

Name of the event

metadata

[string: string]

A loose key-value pair map to add extra information to the system.

Returns:
Promise<void>
Resolves if the event was successfully logged.
Rejects if there is an error.

Usage:

sdk.logMerchantEvent('EventName', {'k1': 'v1', 'k2': 'v2'}).then(() => {
  console.log('logMerchant event successful')
}).catch((err) => {
  console.log('logMerchant Error = ' + err)
})

Get Grant Token (Single Sign-On)

 

fetchGrantToken

Description: This method can be used to verify the identity of a PhonePe user and get his details. The merchant should call this method and get a token, let's call it the grant token. Then the merchant would send this token to their server which in turn sends this to the PhonePe server and gets the user details, thereby verifying the identity of the user. See the service call Get User Details (Service).

Usage:

sdk.fetchGrantToken().then((res) => {
	console.log(grant ‘token data received =  + res)
}).catch((err) => {
	console.log(‘Error occured while fetching the grant token’)
})

Response Parameter

Promise<any>
A promise resolution with the grant token. Promise rejection if the grant token fetching failed.

Promise resolve:
{
  "grantToken": "string",
  "forMerchantId": "string",
  "expiresInSeconds": 0
}

Promise reject:
{
  "error_code": "NETWORK_ERROR"
}

Single Sign-On (Service)

 
posthttps://mercury-uat.phonepe.com/v3/service/access
curl --request POST \
  --url https://mercury-uat.phonepe.com/v3/service/access
var request = require("request");

var options = { method: 'POST',
  url: 'https://mercury-uat.phonepe.com/v3/service/access' };

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/service/access")

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

request = Net::HTTP::Post.new(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/service/access");

xhr.send(data);
import requests

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

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

print(response.text)
A binary file was returned

You couldn't be authenticated

Try the API to see results

Body Params

request
string

base64 encoded payload

Headers

X-VERIFY
string

SHA256(only base64 encoded str+ "/v3/service/access" + salt key) + ### + salt index

Content-Type
string
 

This service gives a merchant the PhonePe's user details corresponding to a grant token. This can be used to facilitate Single Sign-On in the merchant's system as the user details have already been verified by PhonePe.

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256(only base64 encoded str+ "/v3/service/access" + salt key) + ### + salt index

Request Parameters

Parameter Name
Type
Description
Mandatory

merchantId

STRING

Unique MerchantID assigned to the merchant by PhonePe

Yes

grantToken

STRING

Unique grantToken generated by the call to fetchGrantToken as mentioned in the last section Get Grant Token (User Details)

Yes

Response Parameters

Parameter Name
Type
Description

success

BOOLEAN

Success status of the request

code

ENUM

See list of response codes below

data

Object

The data object that has to be passed to the sdk.

Response Codes

Code
Description

UNAUTHORIZED

The grantToken provided is either invalid or not mapped to the merchant.

BAD_REQUEST

Invalid request payload

AUTHORIZATION_FAILED

Incorrect X-VERIFY header

INTERNAL_SERVER_ERROR

Something went wrong

{
  "merchantId": "merchantId",  
  "grantToken": "GRTXXXXX" 
}
{
  "request": "ewoJIm1lcmNoYW50SWQiOiAibWVyY2hhbnRJZCIsICAKICAgICAgICAiZ3JhbnRUb2tlbiI6ICJHUlRYWFhYWCIgCn0K"
}

Initiate Service Request

 
posthttps://mercury-uat.phonepe.com/v3/service/initiate
curl --request POST \
  --url https://mercury-uat.phonepe.com/v3/service/initiate \
  --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/service/initiate',
  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/service/initiate")

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/service/initiate");
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/service/initiate"

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

Try the API to see results

Body Params

request
string
required

base64 encoded payload

Headers

Content-Type
string
required
X-VERIFY
string
required

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

X-CALLBACK-URL
string
required

Dynamic callback URI for server to server callback

 

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256(base64 encoded payload +
"/v3/service/initiate" + salt key) + '###' + salt index

X-CALLBACK-URL

Dynamic callback URI for server to server callback

Every service request has cart details that are typed by the category of that request. Here is an example for the category MOVIE.

The category tree is managed and maintained by PhonePe.

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

amount

INT

Transaction amount in Paise

Yes

validFor

LONG

Time in seconds for which the payment is valid

Yes

quantity

LONG

Quantity of order

Yes

merchantOrderId

STRING

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

Yes

fareType

STRING

fareType is constant and will be provided by PhonePe Team

Yes

merchantOrderContext

Object

trackingUrl key inside this object is used to open the page for this particular order. (User can open this URL through PhonePe's transaction page, "View Details" button)

Yes

mobileNumber

STRING

Mobile number of the user

No

cartDetails

Object

The cart details pertaining to the category

Yes

Response Parameters

Parameter Name
Type
Description

success

BOOLEAN

Success status of the request

code

ENUM

See list of response codes below

data

Object

The data object that has to be passed to the sdk.

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

It's recommended to have the server to server call back using x-callback-url header.

{
  "merchantId": "merchantId",
  "transactionId": "transactionId1",
  "merchantOrderId": "merchantOrderId1",
  "quantity": 1,
  "amount": 5000,
  "validFor": 600,
  "merchantOrderContext": {
		"trackingUrl": "http://test.com/afsd",
		"supportUrl": "http://test.com/support"
	},
  "fareDetails": {
		"category": "SHOPPING",
		"fareBreakup": [{
				"fareType": "TOTAL_FARE",
				"amount": 50000
			},
			{
				"fareType": "BASE_FARE",
				"amount": 45000
			},
			{
				"fareType": "DISCOUNT",
				"amount": 5000
			},
			{
				"fareType": "CONVENIENCE_FEE",
				"amount": 4000
			},
			{
				"fareType": "SERVICE_CHARGE",
				"amount": 4000
			},
			{
				"fareType": "OTHER_CHARGES",
				"amount": 500
			},
			{
				"fareType": "TAX",
				"amount": 500
			}
		]
	},
  "cartDetails": {
    "cartItem": [
      {
        "category": "SHOPPING",
        "itemId": "1234567890",
        "itemName": "Item Name",
        "price": 3000,
        "quantity":1
        "shippingCharge": 4000
      }
    ],
    "cartInfo": {
      "category": "SHOPPING",
      "shippingDate": "2018-09-20",
      "address": {
        "pincode": "560008",
        "city": "Bangalore",
        "addressLine": "Diamond District Domlur"
      }
    }
  }
}
{
  "request": "ewoJIm1lcmNoYW50SWQiOiAiRGVtb21lcmNoYW50IiwKCSJ0cmFuc2FjdGlvbklkIjogIlRYMTIzNDU2Nzg5IiwKCSJhbW91bnQiOiAxMDAsCgkibWVyY2hhbnRPcmRlcklkIjogIk9EMTIzNDY1NiIsCiAgIm1lcmNoYW50T3JkZXJDb250ZXh0IjogewogICAgInRyYWNraW5nVXJsIjogImh0dHBzOi8vZGVtb21lcmNoYW50LmNvbS9ib29raW5nL29yZGVyL3BhZ2UiCiAgfSwKCSJxdWFudGl0eSI6IDEsCgkibW9iaWxlTnVtYmVyIjogIjl4eHh4eHh4eCIsCgkidmFsaWRGb3IiOiAxODAsCgkiY2FydERldGFpbHMiOiB7CgkJImNhcnRJdGVtIjogewoJCQkiY2F0ZWdvcnkiOiAiTU9WSUUiLAoJCQkiaXRlbUlkIjogIlhWR1NEQTMiLAoJCQkibW92aWVOYW1lIjogIlRoZSBBdmVuZ2VycyIsCgkJCSJzY3JlZW5EZXRhaWxzIjogewoJCQkJInNjcmVlbk5vIjogIkF1ZGkgMiIsCgkJCQkidmVudWUiOiAiUFZSIEtvcmFtYW5nYWxhLCBCYW5nYWxvcmUiLAoJCQkJInNlYXRzIjogW3sKCQkJCQkic2VhdE5vIjogIkIxMiIsCgkJCQkJInNlYXRUeXBlIjogIkdPTEQiLAoJCQkJCSJzZWF0UHJpY2UiOiAxMDAKCQkJCX1dLAoJCQkJImRhdGUiOiAiMjItMDMtMjAxOCAxMDoxOTo1NiIKCQkJfSwKCQkJImFkZE9ucyI6IFt7CgkJCQkiYWRkb25UeXBlIjogIkZBTkRCIiwKCQkJCSJpdGVtTmFtZSI6ICJQb3BDb3JuIFBlcHNpIENvbWJvIiwKCQkJCSJxdWFudGl0eSI6IDEsCgkJCQkicHJpY2UiOiAyMDAKCQkJfV0KCQl9Cgl9Cn0="
}

Primary APIs

 

Installation

 


To install PhonePe's React Native SDK, please follow the following steps:

  1. Run npm install phonepesdk

Create PhonePeSDK instance

 

build

(species: string, operatingSystem: 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.

Response Parameter

Promise<PhonePeSDK>

Parameters

Parameter Name
Type
Description

species

string

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

operatingSystem

string

The operatingSystem that the SDK is running on.
Can be either Constants.OS.ios or Constants.OS.android

Usage:

import {PhonePe, Constants} from 'phonepesdk'
let operatingSystem = Constants.OS.ios //or Constants.OS.android
let sdk = await PhonePe.build(Constants.Species.native, operatingSystem)

Show Payments Page

 

openPaymentsPage

(merchantName: string, context: object, imageURL: undefined/string, metaData: undefined/object): Promise<any>
Description: An instance of this class needs to be created and sent to navigateToPage method to open PhonePe's payment 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

Data sent by PhonePe server's service initiate() call Initiate Service Request

imageURL

undefined/string

URL for an image that reflects the merchant's logo

metaData

array of objects

This data is shown in the PhonePe's payments screen as a set of key-value pairs.
example :
[
{
"Name of Products": "Ritz Carlton,Test, XYZ"
},
{
"Number of items": "2"
}
]

Usage:

//Dummy information
let merchantName = "DummyMerchant"
let imageURL = "https://image.dummymerchant.com"
//Any metadata to show on PhonePe's payment screen
let metadata = [{
    "Movie": "Avengers"
}, {"Seats": "3E, 4E, 5E"}]

sdk.openPaymentsPage(merchantName, context, null, imageURL, metadata).then((response) => {
  console.log("Payment was successful = " + response)
}).catch((err) => {
  console.log("Payment failed with error = " + err)
})

Response Parameters

Promise<any>
Promise resolve is called when the payment flow is complete.
Promise reject is called in case of an error.
The promise rejection reasons can be as follows:

Code
Description

PAYMENT_DISMISS

User pressed back button on the payments screen

PAYMENT_TIMEOUT

When the payment timed out based on the timeout interval sent by merchant to PhonePe's server in the payment initiate server call

PARAMS_INVALID_OR_INSUFFICIENT

Invalid or insufficient Parameters sent.

INTERNAL_ERROR

PhonePe's Internal error

Promise resolve:
{}

Promise reject:
{
  'error_code': 'PAYMENT_DISMISS/PAYMENT_TIMEOUT'
}

Ask for Permissions

 


(listOfPermissions: string[]): Promise<any>
Description: This method is used to ask for permissions for accessing user location, reading sms (Android only)

Request Parameter

Parameter Name
Type
Description

listOfPermissions

Array<string>

List of the permissions that you would like to ask for. The permissions you can ask for are described in the table below.

Response Parameters

Promise<any>

Permission Name
Description

READ_SMS (accessed as Constants.Permission. READ_SMS)

Read the user SMS​ for functionalities like OTP detection. Only available for Android.

LOCATION (accessed as Constants.Permission.LOCATION)

Retrieve the user's location.

Usage:

import { Constants } from 'phonepesdk'
let result = await sdk.seekPermission([Constants.Permission.READ_SMS, Constants.Permission.LOCATION])
Promise resolve:
[  
   {  
      "permission":"LOCATION",
      "permissionGranted":true,
      "willShowPermissionAlertAgain": false
   },
   {  
      "permission":"READ_SMS",
      "permissionGranted": true,
      "willShowPermissionAlertAgain": false
   }
]

Get User Location

 

Get Current Location of the User

(): Promise<any>
Description: Call this method to get the current location of the user. You will need to first ask for permission before accessing this method. Refer Ask for Permissions.

Usage

// First ask for user location permission
import { Constants } from 'phonepesdk'

let result = await sdk.seekPermission([Constants.Permission.READ_SMS, Constants.Permission.LOCATION])

//Then ask for location
sdk.getCurrentLocation()
.then((location) => { 
  console.log("Location received with latitude = " + location.latitude + ' longitude = ' + location.longitude)  
})
.catch((err) => { 
  console.log("Error found when fetching location = " + err) 
})

Response Parameters

Promise<any>
Promise resolve is called with user's current location.
Otherwise, Promise reject is called with the appropriate error_code.
The promise rejection reason can be as follows:

Code
Description

LOCATION_FETCH_FAILURE

Unable to fetch user's location

Listening to PhonePe's User Location Updates (Special Usage)

1. Register for location update callbacks

(callbackName: string, callback: LocationResponseCallback): void

Description: Call this method to register your callback for location updates

Request Parameters

Parameter Name
Type
Description

callbackName

string

A unique name for your callback, that will help in uniquely identifying the callback

response

LocationResponseCallback = (response: any): void

A callback to register for user's location updates

Usage:

sdk.registerLocationUpdateSuccessCallback('callbackName', (response) => {
  console.log('Location success response = ' + JSON.stringify(response)) 
})

 //Response
 {
	'latitude': 123.123, 
	'longitude': 345.345
 }

2. (Optional) Register for failure in updating location

(callbackName: string, callback: LocationResponseCallback): void

Description: Call this method to register your callback for location update FAILURES

Usage:

 sdk.registerLocationUpdateFailureCallback('callbackName', (response) => {
   console.log('Location failure response = ' + JSON.stringify(response)) 
 })
 
//Response
 {
   'error_code': 'LOCATION_UPDATE_FAILURE'
 }
   

3. Call startUpdatingLocation API to start receiving callbacks to the registered through registerLocationUpdateSuccessCallback above.

Description: This method is used get continuous location updates of the user. This is used in conjunction with @see registerLocationUpdateSuccessCallback to get notified when a user changes location. You SHOULD call stopUpdatingLocation when done as described in the next section. This helps preserve battery. For fetching location just once getCurrentLocation as stated above in the section "Get Current Location of the User"

Usage:

sdk.startUpdatingLocation()

Stop listening to PhonePe's User Location Updates (Special Usage)

Description: This method is used stop listening to location updates of the user. You should call this method if you don't need to continuously know about the user location. It's very very IMPORTANT to call this method when you would want to stop listening to the location updates. This preserves the user's battery and overall enhances the user experience.

Usage:

sdk.stopUpdatingLocation()
Promise resolve:
{
  'latitude': 123.123, 
  'longitude': 345.345
}

Promise reject:
{
  'error_code': 'LOCATION_FETCH_FAILURE'
}

Key-Value Storage

 


PhonePe provides a key-value storage. Both the keys and values can only be of type string.

getItem

(preferenceName: string, key: string, defaultValue?: undefined⎮string): Promise<string>
Description: This method is used to get a stored value from native key-value storage

Request Parameters

Parameter Name
Type
Description

preferenceName

string

Name of the key-value storage file. A merchant can have multiple key-value storage files for their app

key

string

Name of the key to fetch the value for

defaultValue

undefined/string

Default value in case the key doesn't exist

Usage:

sdk.getItem('app', 'key', undefined)
  .then((data) => {})
  .catch((err) => {})

Response Parameter

Promise<string>
Promise resolve with the value of the corresponding key or the defaultValue if the key doesn't exist.
Otherwise, Promise reject is called with an appropriate error_code.
Promise failure reasons can be as follows:

Code
Description

KEY_NOT_FOUND

No value found for this key and no default value was provided


setItem

(preferenceName: string, key: string, value: string): void
Description: This method is used to store a value (string) for the corresponding key (string) into native key-value storage.

Request Parameters

Parameter Name
Type
Description

preferenceName

string

Name of the key-value storage file. A merchant can have multiple key-value storage files for their app

key

string

Name of the key to set the value for

value

string

Value that you would like to set for the key

Response Parameter

void
Usage:

sdk.setItem('app', 'key', 'value')

removeItem

(preferenceName: string, key: string): void
Description: This method is used remove a key-value pair from native key-value storage

Request Parameters

Parameter Name
Type
Description

preferenceName

string

Name of the key-value storage file. A merchant can have multiple key-value storage files for their app

key

string

Name of the key whose value needs to be removed

Usage:

sdk.removeItem('app', 'key')
Promise resolve:
'valueForKey'

Promise reject:
{
  'error_code': 'KEY_NOT_FOUND'
}

Log Merchant Event

 


(name: string, metadata: [string:string]): Promise<void>
Description: Log an event into the PhonePe ecosystem.

Request Parameters

Parameter Name
Type
Description

name

string

Name of the event

metadata

[string: string]

A loose key-value pair map to add extra information to the system.

Returns:
Promise<void>
Resolves if the event was successfully logged.
Rejects if there is an error.

Usage:

sdk.logMerchantEvent('EventName', 'GroupingKey_123', {'k1': 'v1', 'k2': 'v2'}).then((data) => {
  console.log('logMerchant event successful')
}).catch((err) => {
  console.log('logMerchant Error = ' + err)
})

Load Custom Fonts

 


(name: string, base64FontString: string, type: string): Promise<string>
Description: Load custom fonts (only for React Native implementation). The return value specifies the name to access the font with, which might be different from the name you sent.

Request Parameters

Parameter Name
Type
Description

name

string

Name of the font you would like to keep

base64FontString

string

Base 64 encoded font file

type

string

Only 'ttf' supported for now

Returns:
Promise<string>
Resolves with the name of the font to be used. This might be different than the name sent earlier in the method parameters.
Rejects if there was an issue in adding the font.

Usage:

sdk.loadFont('name', value, 'ttf').then((nameOfTheFont) => {
  console.log('Name received = ' + nameOfTheFont)
}).catch((err) => {
  console.log('Error received = ' + err)
})

Get Grant Token (Single Sign-On)

 

fetchGrantToken

Description: This method can be used to verify the identity of a PhonePe user and get his details. The merchant should call this method and get a token, let's call it grant token. Then the merchant would send this token to their server which in turn sends this to the PhonePe server and gets the user details, thereby verifying the identity of the user. See the service call Get User Details (Service).

Usage:

sdk.fetchGrantToken().then((res) => {
	console.log(grant ‘token data received =  + res)
}).catch((err) => {
	console.log(‘Error occured while fetching the grant token’)
})

Response Parameter

Promise<any>
A promise resolution with the grant token. Promise rejection if the grant token fetching failed.

Promise resolve:
{
  "grantToken": "string",
  "forMerchantId": "string",
  "expiresInSeconds": 0
}

Promise reject:
{
  "error_code": "NETWORK_ERROR"
}

Primary APIs

 

PhonePe Healthcheck

The healthcheck API gives realtime information on health of PhonePe payment systems and reports the downtimes, if any.

 
gethttps://uptime.phonepe.com/v1/merchants/merchantId/health
curl --request GET \
  --url https://uptime.phonepe.com/v1/merchants/merchantId/health \
  --header 'content-type: Content-Type' \
  --header 'x-verify: X-VERIFY'
var request = require("request");

var options = { method: 'GET',
  url:
   'https://uptime.phonepe.com/v1/merchants/merchantId/health',
  headers:
   { 'x-verify': 'X-VERIFY',
     '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://uptime.phonepe.com/v1/merchants/merchantId/health")

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"] = '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://uptime.phonepe.com/v1/merchants/merchantId/health");
xhr.setRequestHeader("content-type", "Content-Type");
xhr.setRequestHeader("x-verify", "X-VERIFY");

xhr.send(data);
import requests

url = "https://uptime.phonepe.com/v1/merchants/merchantId/health"

headers = {
    'content-type': "Content-Type",
    'x-verify': "X-VERIFY"
    }

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

print(response.text)
A binary file was returned

You couldn't be authenticated

{
  "message": "PhonePe is experiencing fluctuations in payments through UPI",
  "overallHealth": "UP",
  "instruments": [
    {
      "instrument": "WALLET",
      "health": "UP",
      "providers": []
    },
    {
      "instrument": "UPI",
      "health": "DEGRADED",
      "providers": [
        {
          "providerType": "BANK",
          "providerId": "UTIB",
          "providerName": "Axis bank",
          "health": "DOWN",
          "reason": "Low success rates"
        }      
]
    },
    {
      "instrument": "CREDIT_CARD",
      "health": "UP",
      "providers": []
    },
    {
      "instrument": "DEBIT_CARD",
      "health": "UP",
      "providers": []
    }
  ]
}

Path Params

merchantId
string
required

Unique Merchant ID assigned to the merchant by PhonePe

Headers

Content-Type
string
required

application/json

X-VERIFY
string
required

SHA256("/v1/merchants/{merchantId}/health" + saltKey) + "###" + saltIndex

 

Path Parameters

Parameter
Type
Description
Mandatory

merchantId

String

Unique Merchant ID assigned to the merchant by PhonePe

Yes

Request Headers

Header Name
Header Value

Content-Type

application/json

X-VERIFY

SHA256("/v1/merchants/{merchantId}/health" + saltKey) + "###" + saltIndex

Response Parameters

Parameter Name
Type
Description / validations

overallHealth

Enum

Overall health of PhonePe (across all instruments).

message

String

Text summary of PhonePe payment’s health

instrument

Enum

Mode through which payment is done, namely ‘WALLET’, ‘UPI’, ‘DEBIT_CARD’ and ‘CREDIT_CARD’

instrument.health

Enum

Health of a particular instrument

providers

Further detailed information on specific providers (banks, etc.) that are down.

Please note that, for simplicity, only providers with “DOWN” health will be included in the response.

Health Types

Enum values for overall, instrument and provider level health

Health Type
Description

UP

Success rates are normal

DEGRADED

There are some fluctuations in success rates

DOWN

Success rates are critically low

Error Codes

Code
Description

BAD_REQUEST

Invalid request

AUTHORIZATION_FAILED

Invalid X-VERIFY header

INTERNAL_SERVER_ERROR

Something went wrong

Deep Offer API

 


Merchants can now pass user and cart context when initiating transaction with PhonePe. This
context can be used to run differential offers and provide differential transaction
experience. This is available for all the platforms(Web, Android, iOS).

Differential Offers

As a part of v3/debit and v3/debit/instant request, merchants need to pass offer context in
following format.

{
  "merchantId": "M12345",
  "transactionId": "TX12345",
  "amount": 100,
  "mobileNumber": "9939872251",
  "merchantContext": {
  	"offerContext": {
  	"tags": [{
    	"id": "GOLD_CATEGORY",
     	"amount": 100 }]
  	}
  }
}

Tag Id are defined in the two (Merchant’s and PhonePe’s) systems in advance operationally
before starting the offer.

For example, we wish to run an offer 10% cashback upto Rs 50 for all Gold Category
customers.

In this case,

  1. A tag GOLD_CATEGORY is defined in both merchant’s and PhonePe’s system
  2. At PhonePe this tag is linked to an offer id that provides 10% cashback upto Rs 50
  3. Whenever a Gold Category customer transacts, Merchant passes tag id as
    GOLD_CATEGORY
  4. PhonePe applies the 10% cashback upto Rs 50 offer.

Note:

  • Currently tag amount should be equal to total amount, else transaction will fail.
  • Merchants can pass more than one tag in tags array, in such cases we can apply best
    offer logic or can add up multiple offers depending on the offer configuration.

Transaction Reversals

No impact on transaction reversals. The reversal signature remains the same.

Offer Discovery

Primary offer discovery should happen at merchant’s site. However to ensure user does not
lose transaction context, the offer information will be shown inside PhonePe container as well.
PFB the screenshot, how an offer is displayed for a user.