Payout Seamless UPI Integration
For onboarding in both the UAT and production environments, the merchant needs to provide the following information:
Technical Information Required:
IP Address: (For dynamic IPs, please provide a range of IP addresses.)
Callback URL/WebHook URL: This is used to notify your server of any changes in transaction status from our back office.
Once the merchant has provided all the required technical details, we will complete the necessary configuration in our back office and provide the Merchant ID (MID/PID) along with login credentials.
Let's see how it works:
The merchant will send a payout request through our API. Along with that, the merchant has to send the customer's UPI id, account_holder, the amount, payment_mode as upi.
Once we receive the request in the correct format, we will share a payment reference string (ref_code) that is necessary for any future references or actions related to the transaction.
After the payout is processed, whether successful or failed, we will send callback data to the provided callback URL (WebHook URL) with the details of the transaction.
To confirm the status of the payout, the merchant can use the polling API to check the current status and update their system accordingly with the payment outcome. (Status Polling)
PAYOUT REQUEST :
Before proceeding with this section of the document, the developer must review the basic workflow. This page explains how to submit a payment request.
Note: All requests must originate from whitelisted IP addresses. (Please ensure that your IP is whitelisted before making a request.)
Payout Request
POST https://<domain>/payout/api/request.php
Headers
Content-Type
application/json
Body
payment_mode
string
upi
Yes
pid
string
provided MID/PID
Yes
order_id
string
unique order id(10 to 13 alphanumeric string)
Yes
amount
int
amount
Yes
upi_id
string
Receiver's UPI VPA
Yes
account_holder
string
Receiver's account name
Yes
email
string
Receiver's email
Yes
phone
string
Receiver's phone number
Yes
{
"payment_mode":"upi",
"pid":"2323232323",
"order_id":"6876mhnytg",
"amount": 8128,
"upi_id":"3223mdsds@upi",
"account_holder":"sanu",
"email":"[email protected]",
"phone":"8754850254"
}Sample Response Body
{
"ref_code":"7701004b34f1db47cbf7edf3eb376703158df1e88b4c1c4a8b2b04d9ebe500d07683f0f5615eccc0c038cb621823f0aadb6df1adc44904e0ba1044c0cbcbeb4e",
"status":"Pending",
"message":"Request Saved successfully"
}{
"status":"error",
"message":"error message"
}CALLBACK
We trigger your callback URL whenever there is a change in the transaction status.
Valid Transaction status are:
Approved
Declined
Pending
Processing
Failed
Refunded
The most famous transaction changes are (but not limited):
Pending => Processing
Pending => Approved
Pending => Declined/Failed
Approved => Declined/Failed
The callback landing page must be hosted on your server at a secret path, but it should still be publicly accessible from our whitelisted IPs. (Please ensure you accept data only from our IPs by implementing proper IP whitelisting.)
In the POST body, you will receive the following properties in JSON format:
order_id
string
Your order id shared
requested_amount
int
requested amount
processed_amount
int
received amount
bank_reference
string
bank reference/UTR details if available
sender_pg
string
sender account name id if available
ref_code
string
unique code for the transaction
status
string
status of payment at this time
post_hash
string
post hash for security verification
payment_type
string
payment type
request_time
string
payment request time
action_time
string
payment made time
upi_vpa
string
receiver vpa if available
account_no
string
receiver account number
account_holder
string
receiver name
ifsc
string
receiver IFSC code
bank_name
string
receiver bank name if available
bank_address
string
receiver bank address if available
transaction_info
array
status change log of transaction
Follow the steps to verify the integrity of received data:
Capture and Decode the Payload
Capture the raw JSON data from the POST body and decode it into an array or object. The following examples assume you have this data in a variable named $array (PHP), array (JavaScript), or array (Python).
// Capture and decode the raw POST body
$data = file_get_contents("php://input");
$array = json_decode($data, true);// In Node.js (e.g., with Express.js)
// This is typically handled by middleware:
// app.use(express.json());
// const array = req.body;# In Python (e.g., with Flask)
# array = request.get_json()Extract and Decrypt the Remote Hash
First, extract the post_hash string from the JSON payload and Base64-decode it. Then, pass the resulting binary data to the decrypt function (provided in the reference section below).
// Get the Base64 string from the array
$post_hash_base64 = $array['post_hash'];
// Decode it to get the raw binary ciphertext
$ivHashCiphertext = base64_decode($post_hash_base64);
//$secret_key is your provided SECRET KEY
// Decrypt using the function from the reference section below
$remote_hash = decrypt($ivHashCiphertext, $secret_key);const postHashBase64 = array.post_hash;
// Decode it to get the raw binary buffer
const ivHashCiphertext = Buffer.from(postHashBase64, 'base64');
// const secret_key = "YOUR_SECRET_KEY";
// Decrypt using the function from the reference section below
const remote_hash = decrypt(ivHashCiphertext, secret_key);import base64
# secret_key = "YOUR_SECRET_KEY"
post_hash_base64 = array['post_hash']
# Decode it to get the raw binary data
ivHashCiphertext = base64.b64decode(post_hash_base64)
# Decrypt using the function from the reference section below
remote_hash = decrypt(ivHashCiphertext, secret_key)The decrypt function for your language is provided in the reference section below.
function decrypt($ivHashCiphertext, $password)
{
$method = "AES-256-CBC";
$iv = substr($ivHashCiphertext, 0, 16);
$hash = substr($ivHashCiphertext, 16, 32);
$ciphertext = substr($ivHashCiphertext, 48);
$key = hash('sha256', $password, true);
if (!hash_equals(hash_hmac('sha256', $ciphertext . $iv, $key, true),$hash))
return null;
return openssl_decrypt($ciphertext, $method, $key,
OPENSSL_RAW_DATA, $iv);
}const crypto = require('crypto');
/**
* @param {Buffer} ivHashCiphertext - The raw binary data (Buffer) after Base64-decoding.
* @param {string} password - Your secret key.
* @returns {string|null} The decrypted plaintext or null on failure.
*/
function decrypt(ivHashCiphertext, password) {
const method = 'aes-256-cbc';
// Extract the initialization vector (first 16 bytes)
const iv = ivHashCiphertext.slice(0, 16);
// Extract the hash (next 32 bytes)
const hash = ivHashCiphertext.slice(16, 48);
// Extract the ciphertext (remaining bytes)
const ciphertext = ivHashCiphertext.slice(48);
// Generate the key using SHA-256 hash of the password
const key = crypto.createHash('sha256').update(password, 'utf8').digest();
// Compute HMAC-SHA256 of (ciphertext || iv) using the key
const hmac = crypto.createHmac('sha256', key)
.update(Buffer.concat([ciphertext, iv]))
.digest();
// Compare the computed HMAC with the extracted hash
if (!crypto.timingSafeEqual(hmac, hash)) {
return null; // Hashes do not match; return null
}
try {
// Decrypt the ciphertext using AES-256-CBC
const decipher = crypto.createDecipheriv(method, key, iv);
const plaintext = Buffer.concat([
decipher.update(ciphertext),
decipher.final()
]);
return plaintext.toString('utf8'); // Return the decrypted text as a UTF-8 string
} catch (err) {
// Decryption failed; return null
return null;
}
}import hashlib
import hmac
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
def decrypt(ivHashCiphertext, password):
"""
Decrypts the iv/hash/ciphertext blob.
:param ivHashCiphertext: The raw binary data (after base64-decoding).
:param password: Your secret key string.
:return: The decrypted plaintext string, or None on failure.
"""
try:
# 1. Extract the components
iv = ivHashCiphertext[:16]
hash_val = ivHashCiphertext[16:48]
ciphertext = ivHashCiphertext[48:]
# 2. Generate the key
key = hashlib.sha256(password.encode('utf-8')).digest()
# 3. Verify the HMAC
computed_hash = hmac.new(key, ciphertext + iv, hashlib.sha256).digest()
if not hmac.compare_digest(computed_hash, hash_val):
return None
# 4. Decrypt the ciphertext
backend = default_backend()
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend)
decryptor = cipher.decryptor()
# Decrypt and unpad
# Using PKCS7 unpadder explicitly is more robust
decrypted_padded_text = decryptor.update(ciphertext) + decryptor.finalize()
unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
decrypted_text = unpadder.update(decrypted_padded_text) + unpadder.finalize()
return decrypted_text.decode('utf-8')
except Exception as e:
# Catch any error (e.g., bad padding, bad key) and return None
# print(f"Decryption failed: {e}") # Optional: for debugging
return NoneCompute the Local Hash
Compute the local hash using the MD5 128-bit hashing algorithm. The hash is created by concatenating the order_id, amount_processed, and status from the callback payload, followed by your secret_key.
// Get the values from the same callback $array
$order_id = $array['order_id'];
$processed_amount = (string)$array['processed_amount'];
$status = $array['status'];
$local_hash = md5($order_id . $processed_amount . $status . $secret_key);const crypto = require('crypto');
// Get the values from the same callback array
const order_id = array.order_id;
// Use (value ?? '') to handle both null AND undefined
const processed_amount = String(array.processed_amount ?? '');
const status = array.status;
const local_hash = crypto
.createHash('md5')
.update(order_id + processed_amount + status + secret_key)
.digest('hex');import hashlib
# Get the values from the same callback array (dict)
order_id = array['order_id']
# Use .get() to safely handle a missing key
processed_amount_val = array.get('processed_amount')
# Convert None to "" and numbers to "100"
processed_amount = "" if processed_amount_val is None else str(processed_amount_val)
status = array['status']
local_hash = hashlib.md5((order_id + processed_amount + status + secret_key).encode('utf-8')).hexdigest()Compare the Hashes
Securely compare the decrypted remote_hash with the local_hash you just computed.
if ($remote_hash !== null && hash_equals($local_hash, $remote_hash)) {
// Mark the transaction as success & process the order
$hash_status = "Hash Matched";
} else {
// Verification failed
$hash_status = "Hash Mismatch";
}let hash_status = "Hash Mismatch";
try {
// Use crypto.timingSafeEqual for secure comparison
// Note: Both hashes must be utf8-encoded strings
const localHashBuffer = Buffer.from(local_hash, 'utf8');
const remoteHashBuffer = Buffer.from(remote_hash, 'utf8');
if (localHashBuffer.length === remoteHashBuffer.length &&
crypto.timingSafeEqual(localHashBuffer, remoteHashBuffer)) {
hash_status = "Hash Matched";
}
} catch (e) {
// hash_status remains "Hash Mismatch"
}import hmac
if remote_hash and hmac.compare_digest(local_hash, remote_hash):
hash_status = "Hash Matched"
else:
hash_status = "Hash Mismatch"Acknowledge the Payment Gateway
To confirm you have received the callback and to prevent our gateway from sending retries, you must do two things:
a. Respond with an HTTP 200 OK status code.
b. Respond with a JSON body containing the key "acknowledge" set to the string "yes".
// --- THIS IS THE IMPORTANT PART ---
// 1. Send an HTTP 200 OK status code
http_response_code(200);
// 2. Prepare the required JSON response
$response = [
'acknowledge' => 'yes',
'hash_status' => $hash_status // Optional: for your own logs
];
// 3. Send the response
header('Content-Type: application/json; charset=utf-8');
echo json_encode($response);
exit;// In Node.js with Express
// This sends both the 200 status and the JSON body
res.status(200).json({
acknowledge: 'yes',
hash_status: hash_status
});# In Python with Flask
from flask import jsonify
response = {
'acknowledge': 'yes',
'hash_status': hash_status
}
# This sends both the 200 status and the JSON body
return jsonify(response), 200STATUS POLLING :
POST https://<domain>/payout/api/status_polling.php
This API is used to poll the status of a specific transaction.
Headers
Content-Type
application/json
Body
pid
string
Provided Merchant ID/PID
ref_code
string
unique ref_code which is generated in payout request
post_hash
string
we will explain how to generate this
Steps to generate post_hash :
Generate the Request
post_hash
1.1 Create Plaintext Hash: Concatenate the ref_code, pid, and your secret_key, then create an MD5 hash.
$ref_code = "YOUR_REF_CODE";
$pid = "YOUR_PID";
$secret_key = "YOUR_SECRET_KEY";
$local_hash = md5($ref_code . $pid . $secret_key);const crypto = require('crypto');
const ref_code = "YOUR_REF_CODE";
const pid = "YOUR_PID";
const secret_key = "YOUR_SECRET_KEY";
const local_hash = crypto
.createHash('md5')
.update(ref_code + pid + secret_key)
.digest('hex');
import hashlib
ref_code = "YOUR_REF_CODE"
pid = "YOUR_PID"
secret_key = "YOUR_SECRET_KEY"
local_hash = hashlib.md5((ref_code + pid + secret_key).encode('utf-8')).hexdigest()1.2 Encrypt the Hash: Encrypt the $local_hash using the encrypt function shown below.
$encrypted_hash = encrypt($local_hash, $secret_key);function encrypt($plaintext, $password)
{
$method = "AES-256-CBC";
$key = hash('sha256', $password, true);
$iv = openssl_random_pseudo_bytes(16);
$ciphertext = openssl_encrypt($plaintext, $method, $key,
OPENSSL_RAW_DATA, $iv);
$hash = hash_hmac('sha256', $ciphertext . $iv, $key, true);
return $iv . $hash . $ciphertext;
}import hashlib
import hmac
import os
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding as crypto_padding
def encrypt(plaintext, password):
key = hashlib.sha256(password.encode('utf-8')).digest()
iv = os.urandom(16)
cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext_bytes = plaintext.encode('utf-8')
padded_plaintext = pad(plaintext_bytes, AES.block_size)
ciphertext = cipher.encrypt(padded_plaintext)
hash_value = hmac.new(key, ciphertext + iv, hashlib.sha256).digest()
return iv + hash_value + ciphertextconst crypto = require('crypto');
function encrypt(plaintext, password) {
const method = 'aes-256-cbc';
const key = crypto.createHash('sha256').update(password, 'utf8').digest();
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(method, key, iv);
let ciphertext = cipher.update(plaintext, 'utf8');
ciphertext = Buffer.concat([ciphertext, cipher.final()]);
const hmac = crypto.createHmac('sha256', key);
hmac.update(Buffer.concat([ciphertext, iv]));
const hash = hmac.digest();
// Return the raw binary Buffer
return Buffer.concat([iv, hash, ciphertext]);
}1.3 Base64 Encode: Base64-encode the raw binary output from the encrypt function. This final string is your post_hash.
Send the POST Request
Send a POST request containing pid, ref_code, and post_hash as a JSON body , and you will receive a response after validating the data.
<?php
// Your transaction data
$pid = "YOUR_PID";
$ref_code = "YOUR_REF_CODE";
$secret_key = "YOUR_SECRET_KEY";
// --- Step 1: Generate Hash ---
$local_hash = md5($ref_code . $pid . $secret_key);
$encrypted_hash = encrypt($local_hash, $secret_key);
$post_hash = base64_encode($encrypted_hash);
// --- Step 2: Send Request ---
$api_url = "https://<domain>/payout/api/status_polling.php";
$data = [
'pid' => $pid,
'ref_code' => $ref_code,
'post_hash' => $post_hash
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $api_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$server_output = curl_exec($ch);
curl_close($ch);
?>Processing the API Response
The API will respond with a JSON object. If the request is successful and the ref_code is found, it will return the transaction details. If it fails (e.g., bad hash, ref_code not found), it will return an error message.
Success Response Parameters
A successful response will contain the following parameters as JSON body:
order_id
string
Your order id shared
requested_amount
int
requested amount
processed_amount
int
received amount
bank_reference
string
bank reference/UTR details if available
sender_pg
string
sender account name id if available
ref_code
string
unique code for the transaction
status
string
status of payment at this time
post_hash
string
post hash for security verification
payment_type
string
payment type
request_time
string
payment request time
action_time
string
payment made time
upi_vpa
string
receiver vpa if available
account_no
string
receiver account number
account_holder
string
receiver name
ifsc
string
receiver IFSC code
bank_name
string
receiver bank name if available
bank_address
string
receiver bank address if available
transaction_info
array
status change log of transaction
Error Response
An error response will contain an error key.
{
"error": "error message"
}Verify the Response
post_hash
Before trusting any data from the response, you must verify its post_hash to ensure the data is from us and has not been tampered with. This verification logic is identical to the logic used for verifying a callback.
You do not need to send an "Acknowledge" response for a status poll.
4.1 Compute the Local Hash
From the JSON response, get the order_id, processed_amount, and status. Concatenate them with your secret_key and create an MD5 hash.
// $response_data is the decoded JSON response from /api/status_polling.php
$order_id = $response_data['order_id'];
$processed_amount = (string)$response_data['processed_amount'];
$status = $response_data['status'];
$local_hash = md5($order_id . $processed_amount. $status . $secret_key);// responseData is the parsed JSON response
const order_id = responseData.order_id;
// Use (value ?? '') to default null/undefined to '', then convert to string
const processed_amount = String(responseData.processed_amount ?? '');
const status = responseData.status;
const local_hash = crypto
.createHash('md5')
.update(order_id.toString() + processed_amount.toString() + status.toString() + secret_key)
.digest('hex');# response_data is the parsed JSON response (a dict)
order_id = response_data['order_id']
# Safely convert None to '' or a number to str
processed_amount_val = response_data['processed_amount']
processed_amount = str(processed_amount_val) if processed_amount_val is not None else ''
status = response_data['status']
local_hash = hashlib.md5((order_id + processed_amount + status + secret_key).encode('utf-8')).hexdigest()4.2 Decrypt the Remote Hash
Get the post_hash string from the JSON response. Base64-decode it, then pass the raw binary data to the decrypt function.
// Get the Base64 string from the response
$post_hash_base64 = $response_data['post_hash'];
// Decode it to get the raw binary ciphertext
$ivHashCiphertext = base64_decode($post_hash_base64);
// Decrypt using the function from the reference section below
$remote_hash = decrypt($ivHashCiphertext, $secret_key);const postHashBase64 = responseData.post_hash;
// Decode it to get the raw binary buffer
const ivHashCiphertext = Buffer.from(postHashBase64, 'base64');
// Decrypt using the function from the reference section below
const remote_hash = decrypt(ivHashCiphertext, secret_key);import base64
post_hash_base64 = response_data['post_hash']
# Decode it to get the raw binary data
ivHashCiphertext = base64.b64decode(post_hash_base64)
# Decrypt using the function from the reference section below
remote_hash = decrypt(ivHashCiphertext, secret_key)The decrypt function for your language is provided in the reference section below.
function decrypt($ivHashCiphertext, $password)
{
$method = "AES-256-CBC";
$iv = substr($ivHashCiphertext, 0, 16);
$hash = substr($ivHashCiphertext, 16, 32);
$ciphertext = substr($ivHashCiphertext, 48);
$key = hash('sha256', $password, true);
if (!hash_equals(hash_hmac('sha256', $ciphertext . $iv, $key, true),$hash))
return null;
return openssl_decrypt($ciphertext, $method, $key,
OPENSSL_RAW_DATA, $iv);
}const crypto = require('crypto');
/**
* @param {Buffer} ivHashCiphertext - The raw binary data (Buffer) after Base64-decoding.
* @param {string} password - Your secret key.
* @returns {string|null} The decrypted plaintext or null on failure.
*/
function decrypt(ivHashCiphertext, password) {
const method = 'aes-256-cbc';
// Extract the initialization vector (first 16 bytes)
const iv = ivHashCiphertext.slice(0, 16);
// Extract the hash (next 32 bytes)
const hash = ivHashCiphertext.slice(16, 48);
// Extract the ciphertext (remaining bytes)
const ciphertext = ivHashCiphertext.slice(48);
// Generate the key using SHA-256 hash of the password
const key = crypto.createHash('sha256').update(password, 'utf8').digest();
// Compute HMAC-SHA256 of (ciphertext || iv) using the key
const hmac = crypto.createHmac('sha256', key)
.update(Buffer.concat([ciphertext, iv]))
.digest();
// Compare the computed HMAC with the extracted hash
if (!crypto.timingSafeEqual(hmac, hash)) {
return null; // Hashes do not match; return null
}
try {
// Decrypt the ciphertext using AES-256-CBC
const decipher = crypto.createDecipheriv(method, key, iv);
const plaintext = Buffer.concat([
decipher.update(ciphertext),
decipher.final()
]);
return plaintext.toString('utf8'); // Return the decrypted text as a UTF-8 string
} catch (err) {
// Decryption failed; return null
return null;
}
}import hashlib
import hmac
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
def decrypt(ivHashCiphertext, password):
"""
Decrypts the iv/hash/ciphertext blob.
:param ivHashCiphertext: The raw binary data (after base64-decoding).
:param password: Your secret key string.
:return: The decrypted plaintext string, or None on failure.
"""
try:
# 1. Extract the components
iv = ivHashCiphertext[:16]
hash_val = ivHashCiphertext[16:48]
ciphertext = ivHashCiphertext[48:]
# 2. Generate the key
key = hashlib.sha256(password.encode('utf-8')).digest()
# 3. Verify the HMAC
computed_hash = hmac.new(key, ciphertext + iv, hashlib.sha256).digest()
if not hmac.compare_digest(computed_hash, hash_val):
return None
# 4. Decrypt the ciphertext
backend = default_backend()
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend)
decryptor = cipher.decryptor()
# Decrypt and unpad
# Using PKCS7 unpadder explicitly is more robust
decrypted_padded_text = decryptor.update(ciphertext) + decryptor.finalize()
unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
decrypted_text = unpadder.update(decrypted_padded_text) + unpadder.finalize()
return decrypted_text.decode('utf-8')
except Exception as e:
# Catch any error (e.g., bad padding, bad key) and return None
# print(f"Decryption failed: {e}") # Optional: for debugging
return None4.3 Compare the Hashes
Securely compare the local_hash you just computed with the remote_hash you decrypted. If they match, you can trust the data.
if ($remote_hash !== null && hash_equals($local_hash, $remote_hash)) {
// --- SUCCESS: Data is verified ---
// You can now trust the data and update your database.
// echo "Status: " . $response_data['status'];
} else {
// --- FAILURE: Hash mismatch! ---
// Do NOT trust this data.
}let isVerified = false;
if (remote_hash) {
// Use crypto.timingSafeEqual for secure comparison
try {
const localHashBuffer = Buffer.from(local_hash, 'utf8');
const remoteHashBuffer = Buffer.from(remote_hash, 'utf8');
if (localHashBuffer.length === remoteHashBuffer.length) {
isVerified = crypto.timingSafeEqual(localHashBuffer, remoteHashBuffer);
}
} catch (e) {
// Error during buffer creation (e.g., bad hash)
isVerified = false;
}
}
if (isVerified) {
// --- SUCCESS: Data is verified ---
// console.log("Status:", responseData.status);
} else {
// --- FAILURE: Hash mismatch! ---
}import hmac
isVerified = False
if remote_hash:
# Use hmac.compare_digest for secure comparison
isVerified = hmac.compare_digest(local_hash, remote_hash)
if isVerified:
# --- SUCCESS: Data is verified ---
# print(f"Status: {response_data['status']}")
pass
else:
# --- FAILURE: Hash mismatch! ---
passTRANSACTION STATUS :
Approved: Payment has been successfully approved by our system.
Failed: Payment failed on the bank's side.
Processing: The bank is currently processing the payment.
Declined: Payment has been declined by our system.
Pending: The user session is active, and the payment is awaiting completion.
Refunded : The amount is refunded to customer
ERROR :
No valid channel found : This error raise if no active channel/provider mapped against your MID
Bank error , please contact admin : Unknown bank side error
Hash value is not defined : This error raises for status check if the provided hash is not matched with genereted one
Ref code does not exist : This error raise in the status check , if ref_code is not provided for status check
COMPLAINT
We have a dedicated Complaint Section where merchants can manage transaction-related complaints. Through this section, merchants can submit complaints with all necessary details and optional evidence. Upon submission, a unique complaint reference ID is generated, allowing merchants to track the complaint’s status and receive real-time updates via the status-check API. This ensures a smooth, secure, and efficient process for resolving any transaction issues.
RECONCILIATION
This API endpoint allows authorized users to retrieve approved payout transactions based on a specific pid (Partner ID) and date. The API performs authentication using a token and signature verification to ensure secure communication.
PAYOUT STATUS CHECK
This API endpoint allows you to check the status of a specific payout transaction. It authenticates requests using a partner ID (pid) and a securely hashed signature.
Last updated