NexaPay API Reference

Welcome to the NexaPay REST API documentation. NexaPay provides a lightweight, robust UPI-focused payment gateway engine that detects actual QR payments via Paytm Business API endpoints.

Using our APIs, you can easily create checkout orders, generate dynamic payment landing links, redirect customers, verify transactions instantly, and receive real-time webhook status updates once they finish paying.

Developer Mode Detected

We are currently showing fallback demo keys in code snippets. Log in to your account to automatically populate these docs with your actual merchant credentials.

Authentication

All REST API endpoints require secure authentication headers. Your credentials consist of a live public Key and a secret Key which you must generate inside your API Settings page.

Include the keys as custom HTTP headers with every request:

Header Name Description Example
X-API-Key Your merchant environment API Key. pi_live_xxxxxxxxxxxxxxxxxxxxxxxx
X-API-Secret Your merchant environment API Secret. Keep this safe! sk_live_xxxxxxxxxxxxxxxxxxxxxxxx
Content-Type Payload type indicator (must be JSON). application/json
Keep Secrets Confidential

Never share your API Secret or commit it to client-side code repositories. Always trigger requests to our API endpoint servers from your backend server application.

Environments

NexaPay supports two environments. You can toggle your environment mode within your Merchant Developer Console.

  1. Sandbox Mode (Test): Used during integration testing. Checkout links will load a simulated payment page where you can trigger a successful payment callback instantly without transferring money. Use headers containing your sandbox credentials.
  2. Production Mode (Live): Process actual transaction amounts. Integrates directly with your connected Paytm Merchant accounts to generate live UPI codes and poll transaction records.

The base endpoint URL remains the same for both test and live environments:

Base Endpoint URL
https://mail.nexapay.online/api

Create Order

POST https://mail.nexapay.online/api/create-order

Creates a transaction order in our database and returns a unique, secure `payment_url`. Redirect your customer to this URL to trigger the checkout flow.

Request Body Parameters

Parameter Type Required Description
amount float Yes The order amount in INR. Must be greater than 0.00.
order_id string Yes Your internal unique transaction identifier (e.g. ORD98765).
customer_name string Yes The billing customer's full name.
callback_url string No Redirect destination URL once payment completes.
description string No Payment remarks shown to the customer (e.g. Pro plan renewal).
customer_mobile string No Customer's phone number.
is_reusable boolean No Set to true if you want this link to accept multiple customer payments (default: false).
curl -X POST https://mail.nexapay.online/api/create-order \
  -H "X-API-Key: pi_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "X-API-Secret: sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "100.00",
    "order_id": "ORD_20260703_4454",
    "customer_name": "Raushan Kumar",
    "description": "Order simulation purchase",
    "callback_url": "https://yourwebsite.com/callback.php"
  }'
<?php
$payload = [
    'amount' => '100.00',
    'order_id' => 'ORD_20260703_4454',
    'customer_name' => 'Raushan Kumar',
    'description' => 'Order simulation purchase',
    'callback_url' => 'https://yourwebsite.com/callback.php'
];

$ch = curl_init('https://mail.nexapay.online/api/create-order');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode($payload),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'X-API-Key: pi_live_xxxxxxxxxxxxxxxxxxxxxxxx',
        'X-API-Secret: sk_live_xxxxxxxxxxxxxxxxxxxxxxxx'
    ]
]);

$response = curl_exec($ch);
$data = json_decode($response, true);
curl_close($ch);

if (isset($data['status']) && $data['status'] === 'success') {
    $checkoutUrl = $data['data']['payment_url'];
    // Redirect customer to $checkoutUrl
    header("Location: " . $checkoutUrl);
    exit;
} else {
    echo "Error creating order: " . ($data['error'] ?? 'Unknown error');
}
?>
const fetch = require('node-fetch');

const payload = {
  amount: '100.00',
  order_id: 'ORD_20260703_4454',
  customer_name: 'Raushan Kumar',
  description: 'Order simulation purchase',
  callback_url: 'https://yourwebsite.com/callback.php'
};

fetch('https://mail.nexapay.online/api/create-order', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'pi_live_xxxxxxxxxxxxxxxxxxxxxxxx',
    'X-API-Secret': 'sk_live_xxxxxxxxxxxxxxxxxxxxxxxx'
  },
  body: JSON.stringify(payload)
})
.then(res => res.json())
.then(json => {
  if (json.status === 'success') {
    console.log('Redirect URL:', json.data.payment_url);
  } else {
    console.error('API Error:', json.error);
  }
})
.catch(err => console.error(err));
import requests

payload = {
    "amount": "100.00",
    "order_id": "ORD_20260703_4454",
    "customer_name": "Raushan Kumar",
    "description": "Order simulation purchase",
    "callback_url": "https://yourwebsite.com/callback.php"
}

headers = {
    "Content-Type": "application/json",
    "X-API-Key": "pi_live_xxxxxxxxxxxxxxxxxxxxxxxx",
    "X-API-Secret": "sk_live_xxxxxxxxxxxxxxxxxxxxxxxx"
}

response = requests.post("https://mail.nexapay.online/api/create-order", json=payload, headers=headers)
data = response.json()

if data.get("status") == "success":
    print("Redirect user to:", data["data"]["payment_url"])
else:
    print("Error:", data.get("error"))

Success Response Schema (201 Created)

201 Created Response
{
  "status": "success",
  "message": "Order created successfully",
  "data": {
    "payment_url": "https://mail.nexapay.online/pay/LRd7jTFOV2sFyhMyOBzbJLL1SQzMxe5V",
    "order_id": "ORD_20260703_4454",
    "token": "LRd7jTFOV2sFyhMyOBzbJLL1SQzMxe5V",
    "amount": 100.00,
    "currency": "INR",
    "customer_name": "Raushan Kumar",
    "expires_at": "2026-06-06 11:15:30",
    "created_at": "2026-06-05 11:15:30"
  }
}

Check Status

POST https://mail.nexapay.online/api/check-status

Retrieves the details and verification status of a transaction using your unique `order_id` reference.

Request Body Parameters

Parameter Type Required Description
order_id string Yes The unique order ID reference you sent during order creation.
curl -X POST https://mail.nexapay.online/api/check-status \
  -H "X-API-Key: pi_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "X-API-Secret: sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "order_id": "ORD_20260703_4454"
  }'
<?php
$payload = [
    'order_id' => 'ORD_20260703_4454'
];

$ch = curl_init('https://mail.nexapay.online/api/check-status');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode($payload),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'X-API-Key: pi_live_xxxxxxxxxxxxxxxxxxxxxxxx',
        'X-API-Secret: sk_live_xxxxxxxxxxxxxxxxxxxxxxxx'
    ]
]);

$response = curl_exec($ch);
$data = json_decode($response, true);
curl_close($ch);

if (isset($data['status']) && $data['status'] === 'success') {
    $paymentStatus = $data['data']['payment_status']; // 'success', 'pending', or 'failed'
    echo "Transaction Status: " . strtoupper($paymentStatus);
} else {
    echo "Error checking status: " . ($data['error'] ?? 'Unknown error');
}
?>
const fetch = require('node-fetch');

fetch('https://mail.nexapay.online/api/check-status', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'pi_live_xxxxxxxxxxxxxxxxxxxxxxxx',
    'X-API-Secret': 'sk_live_xxxxxxxxxxxxxxxxxxxxxxxx'
  },
  body: JSON.stringify({ order_id: 'ORD_20260703_4454' })
})
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error(err));

Success Response Schema (200 OK)

200 OK Response
{
  "status": "success",
  "data": {
    "order_id": "ORD_20260703_4454",
    "amount": 100.00,
    "currency": "INR",
    "payment_status": "success",
    "customer_name": "Raushan Kumar",
    "customer_mobile": "9999999999",
    "utr": "615372849102",
    "payment_method": "UPI QR",
    "provider": "paytm",
    "gateway_txn_id": "TXN_9201938561",
    "paid_at": "2026-06-05 11:16:45",
    "payment_url": "https://mail.nexapay.online/pay/LRd7jTFOV2sFyhMyOBzbJLL1SQzMxe5V",
    "callback_url": "https://yourwebsite.com/callback.php",
    "expires_at": "2026-06-06 11:15:30",
    "created_at": "2026-06-05 11:15:30"
  }
}

Create Payout

POST https://mail.nexapay.online/api/create-payout

Initiates a payout (withdrawal) from your NexaPay settlement balance to a bank account, UPI ID, or USDT wallet. The amount is deducted from your available wallet balance once the payout is processed successfully.

Wallet Balance Required

Payouts are debited from your available settlement balance. Ensure you have sufficient balance and that payouts are enabled for your account before calling this endpoint.

Request Body Parameters

Parameter Type Required Description
amount float Yes Payout amount in INR. Between ₹100 and ₹5,00,000.
method string Yes Payout method: bank, upi, or usdt.
account_holder string Yes Full name of the beneficiary / account holder.
account_number string Bank only Beneficiary bank account number. Required when method = bank.
ifsc_code string Bank only 11-character IFSC code. Required when method = bank.
bank_name string Bank only Beneficiary bank name. Required when method = bank.
upi_id string UPI only Beneficiary UPI ID (e.g. name@bank). Required when method = upi.
usdt_wallet_address string USDT only Beneficiary USDT wallet address (alphanumeric, 20–100 chars). Required when method = usdt.
remark string No Optional note saved with the payout for your records.
curl -X POST https://mail.nexapay.online/api/create-payout \
  -H "X-API-Key: pi_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "X-API-Secret: sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "1000.00",
    "method": "bank",
    "account_holder": "Raushan Kumar",
    "account_number": "1234567890",
    "ifsc_code": "SBIN0001234",
    "bank_name": "State Bank of Pay",
    "remark": "Weekly settlement"
  }'
<?php
$payload = [
    'amount' => '1000.00',
    'method' => 'bank', // or 'upi' / 'usdt'
    'account_holder' => 'Raushan Kumar',
    'account_number' => '1234567890',
    'ifsc_code' => 'SBIN0001234',
    'bank_name' => 'State Bank of Pay',
    'remark' => 'Weekly settlement'
];

$ch = curl_init('https://mail.nexapay.online/api/create-payout');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode($payload),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'X-API-Key: pi_live_xxxxxxxxxxxxxxxxxxxxxxxx',
        'X-API-Secret: sk_live_xxxxxxxxxxxxxxxxxxxxxxxx'
    ]
]);

$response = curl_exec($ch);
$data = json_decode($response, true);
curl_close($ch);

if (isset($data['status']) && $data['status'] === 'success') {
    $payoutId = $data['data']['payout_id'];
    echo "Payout created: " . $payoutId . " (" . $data['data']['payout_status'] . ")";
} else {
    echo "Error creating payout: " . ($data['details'] ?? $data['error'] ?? 'Unknown error');
}
?>
const fetch = require('node-fetch');

const payload = {
  amount: '1000.00',
  method: 'bank', // or 'upi' / 'usdt'
  account_holder: 'Raushan Kumar',
  account_number: '1234567890',
  ifsc_code: 'SBIN0001234',
  bank_name: 'State Bank of Pay',
  remark: 'Weekly settlement'
};

fetch('https://mail.nexapay.online/api/create-payout', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'pi_live_xxxxxxxxxxxxxxxxxxxxxxxx',
    'X-API-Secret': 'sk_live_xxxxxxxxxxxxxxxxxxxxxxxx'
  },
  body: JSON.stringify(payload)
})
.then(res => res.json())
.then(json => {
  if (json.status === 'success') {
    console.log('Payout ID:', json.data.payout_id);
  } else {
    console.error('API Error:', json.details || json.error);
  }
})
.catch(err => console.error(err));
import requests

payload = {
    "amount": "1000.00",
    "method": "bank",  # or "upi" / "usdt"
    "account_holder": "Raushan Kumar",
    "account_number": "1234567890",
    "ifsc_code": "SBIN0001234",
    "bank_name": "State Bank of Pay",
    "remark": "Weekly settlement"
}

headers = {
    "Content-Type": "application/json",
    "X-API-Key": "pi_live_xxxxxxxxxxxxxxxxxxxxxxxx",
    "X-API-Secret": "sk_live_xxxxxxxxxxxxxxxxxxxxxxxx"
}

response = requests.post("https://mail.nexapay.online/api/create-payout", json=payload, headers=headers)
data = response.json()

if data.get("status") == "success":
    print("Payout ID:", data["data"]["payout_id"])
else:
    print("Error:", data.get("details") or data.get("error"))

UPI Payout Example Body

UPI Request Body
{
  "amount": "1000.00",
  "method": "upi",
  "account_holder": "Raushan Kumar",
  "upi_id": "raushan@paytm",
  "remark": "Weekly settlement"
}

USDT Payout Example Body

USDT Request Body
{
  "amount": "1000.00",
  "method": "usdt",
  "account_holder": "Raushan Kumar",
  "usdt_wallet_address": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
  "remark": "Weekly settlement"
}

Success Response Schema (201 Created)

201 Created Response
{
  "status": "success",
  "message": "Payout request created successfully",
  "data": {
    "payout_id": "PO_20260612145932_12_a1b2c3",
    "amount": 1000.00,
    "currency": "INR",
    "method": "bank",
    "account_holder": "Raushan Kumar",
    "payout_status": "PENDING",
    "created_at": "2026-06-12 14:59:32"
  }
}

Payout Status

POST https://mail.nexapay.online/api/payout-status

Retrieves the current status of a payout using the payout_id returned during creation. The status is refreshed in real time from the payout gateway whenever it is still being processed.

Request Body Parameters

Parameter Type Required Description
payout_id string Yes The payout_id returned by the Create Payout API.
curl -X POST https://mail.nexapay.online/api/payout-status \
  -H "X-API-Key: pi_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "X-API-Secret: sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "payout_id": "PO_20260612145932_12_a1b2c3"
  }'
<?php
$payload = [
    'payout_id' => 'PO_20260612145932_12_a1b2c3'
];

$ch = curl_init('https://mail.nexapay.online/api/payout-status');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode($payload),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'X-API-Key: pi_live_xxxxxxxxxxxxxxxxxxxxxxxx',
        'X-API-Secret: sk_live_xxxxxxxxxxxxxxxxxxxxxxxx'
    ]
]);

$response = curl_exec($ch);
$data = json_decode($response, true);
curl_close($ch);

if (isset($data['status']) && $data['status'] === 'success') {
    echo "Payout Status: " . $data['data']['payout_status'];
    if (!empty($data['data']['utr'])) {
        echo " | UTR: " . $data['data']['utr'];
    }
} else {
    echo "Error checking status: " . ($data['details'] ?? $data['error'] ?? 'Unknown error');
}
?>
const fetch = require('node-fetch');

fetch('https://mail.nexapay.online/api/payout-status', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'pi_live_xxxxxxxxxxxxxxxxxxxxxxxx',
    'X-API-Secret': 'sk_live_xxxxxxxxxxxxxxxxxxxxxxxx'
  },
  body: JSON.stringify({ payout_id: 'PO_20260612145932_12_a1b2c3' })
})
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error(err));

Payout Status Values

Status Meaning
PENDINGPayout created, awaiting approval.
APPROVEDApproved and queued for processing.
PROCESSINGSubmitted to the gateway and being processed.
SUCCESSFunds successfully transferred. A utr is returned.
REJECTEDPayout failed; the amount is refunded to your wallet.
CANCELLEDPayout was cancelled before processing.

Success Response Schema (200 OK)

200 OK Response
{
  "status": "success",
  "data": {
    "payout_id": "PO_20260612145932_12_a1b2c3",
    "amount": 1000.00,
    "currency": "INR",
    "method": "bank",
    "account_holder": "Raushan Kumar",
    "payout_status": "SUCCESS",
    "status_text": "Completed Successfully",
    "utr": "615372849102",
    "remark": "Weekly settlement",
    "created_at": "2026-06-12 14:59:32",
    "processed_at": "2026-06-12 15:04:11",
    "account_number": "1234567890",
    "ifsc_code": "SBIN0001234",
    "bank_name": "State Bank of Pay"
  }
}

Webhooks

Webhooks are used to receive real-time updates directly on your server whenever a transaction is completed successfully. Instead of polling our check status API, we will send an asynchronous HTTP POST request to your configured webhook URL.

You can manage and add webhooks in your Webhooks Portal.

Signature Validation

To ensure webhook payloads are authentically generated by NexaPay, every webhook request contains a custom header named `X-NexaPay-Signature`.

This signature represents the HMAC-SHA256 hash of the raw POST body payload, signed using your unique **Webhook Secret Key**.

Sample PHP Webhook Receiver & Verification

webhook-handler.php
<?php
// Retrieve the signature header
$signature = $_SERVER['HTTP_X_NEXAPAY_SIGNATURE'] ?? '';

// Get Webhook Secret from your settings
$webhookSecret = "your_webhook_secret_key";

// Read raw POST body payload
$payload = file_get_contents('php://input');

// Calculate expected signature
$expectedSignature = hash_hmac('sha256', $payload, $webhookSecret);

// Verify match
if (hash_equals($expectedSignature, $signature)) {
    // Valid request! Parse JSON
    $data = json_decode($payload, true);
    $orderId = $data['order_id'];
    $amount = $data['amount'];
    $utr = $data['utr'];
    $status = $data['status']; // 'success'
    
    if ($data['event'] === 'payment.success') {
        // 1. Mark order as Paid in your database
        // 2. Deliver goods to customer
    }
    
    // Respond with 200 OK to acknowledge receipt
    http_response_code(200);
    echo json_encode(['received' => true]);
} else {
    // Invalid signature, ignore/fail
    http_response_code(400);
    echo "Invalid signature";
}
?>

Callbacks & Redirect

If you passed a `callback_url` when creating the order, NexaPay will automatically redirect your customer's browser to this URL immediately after a successful checkout verification.

When redirecting, we append key transaction details as URL query parameters:

Example Redirect URL
https://yourwebsite.com/callback.php?status=success&order_id=ORD_20260703_4454&amount=100.00&utr=615372849102
Secure Verification Requirement

Browser redirects can easily be modified by malicious users. Never finalize transactions or deliver digital goods based solely on URL parameter states. Always run a backend status check API call or wait for the webhook trigger to confirm the payment was captured.

PHP Integration Flow

Here is a complete, step-by-step implementation showcasing how to create a payment checkout, redirect the user, and process the callback securely.

Complete Integration Sample
<?php
/**
 * Step 1: Initialize Payment Order
 */
function initiatePayment($orderId, $amount, $customerName) {
    $apiKey = "pi_live_xxxxxxxxxxxxxxxxxxxxxxxx";
    $apiSecret = "sk_live_xxxxxxxxxxxxxxxxxxxxxxxx";
    
    $payload = [
        'amount' => number_format($amount, 2, '.', ''),
        'order_id' => $orderId,
        'customer_name' => $customerName,
        'callback_url' => 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . '?action=callback'
    ];

    $ch = curl_init('https://mail.nexapay.online/api/create-order');
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => json_encode($payload),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            'X-API-Key: ' . $apiKey,
            'X-API-Secret: ' . $apiSecret
        ]
    ]);

    $response = curl_exec($ch);
    $data = json_decode($response, true);
    curl_close($ch);

    if (isset($data['status']) && $data['status'] === 'success') {
        // Redirect customer to NexaPay payment card
        header("Location: " . $data['data']['payment_url']);
        exit;
    } else {
        die("Payment initiation failed: " . ($data['error'] ?? 'Unknown Error'));
    }
}

/**
 * Step 2: Handle Browser Redirect Callback
 */
function handleCallback() {
    $orderId = $_GET['order_id'] ?? '';
    $status = $_GET['status'] ?? '';
    
    if (empty($orderId) || $status !== 'success') {
        die("Payment was not successful or was cancelled.");
    }
    
    // Now verify status securely on the backend
    $apiKey = "pi_live_xxxxxxxxxxxxxxxxxxxxxxxx";
    $apiSecret = "sk_live_xxxxxxxxxxxxxxxxxxxxxxxx";
    
    $ch = curl_init('https://mail.nexapay.online/api/check-status');
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => json_encode(['order_id' => $orderId]),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            'X-API-Key: ' . $apiKey,
            'X-API-Secret: ' . $apiSecret
        ]
    ]);

    $response = curl_exec($ch);
    $data = json_decode($response, true);
    curl_close($ch);

    if (isset($data['status']) && $data['status'] === 'success' && $data['data']['payment_status'] === 'success') {
        $amount = $data['data']['amount'];
        $utr = $data['data']['utr'];
        
        echo "<h1 style='color:green;'>Payment Successful!</h1>";
        echo "<p>Thank you, your order <strong>$orderId</strong> of ₹$amount has been paid successfully.</p>";
        echo "<p>UTR Reference: $utr</p>";
    } else {
        echo "<h1 style='color:red;'>Verification Failed</h1>";
        echo "<p>The payment verification returned an unconfirmed status.</p>";
    }
}

// Simple Router Trigger
$action = $_GET['action'] ?? '';
if ($action === 'pay') {
    $randomOrderId = 'ORD_' . uniqid();
    initiatePayment($randomOrderId, 100.00, 'Raushan Kumar');
} elseif ($action === 'callback') {
    handleCallback();
} else {
    // Show initiation button
    echo "<a href='?action=pay' style='padding:12px 24px; background:#0B3D2E; color:#C6E547; text-decoration:none; border-radius:8px; font-family:sans-serif; font-weight:bold;'>Pay ₹100 using NexaPay</a>";
}
?>