PayNXT Developer Documentation

Integrate once and accept payments through PayNXT's orchestration layer. This guide covers authentication, request signing, creating a payment session, redirecting to checkout, and going live.

Overview

The integration is server-to-server. Your backend creates a payment session via the PayNXT API, then redirects the customer to the returned checkout_url. PayNXT handles the gateway (Razorpay today) and notifies you of the result.

Base URL: https://paynxt.xyz

Environments (UAT & Live)

PayNXT supports two modes, controlled by the credentials your PayNXT admin configures for your account:

EnvironmentPurposeGateway mode
TEST UATIntegration testing with test gateway keys. No real money moves.Razorpay TEST
LIVEProduction traffic with live gateway keys.Razorpay LIVE

The same API endpoints and signing scheme apply to both. Your account starts in UAT; an admin enables LIVE once you're approved and live credentials are connected.

Credentials

Your PayNXT admin issues you two values:

If a sign key is leaked, ask your admin to regenerate it — the old key stops working immediately.

Authentication & request signing

Every request to the PayNXT API must be signed. Send these headers:

HeaderValue
X-Merchant-IdYour Merchant ID
X-TimestampCurrent Unix time in milliseconds (must be within 5 minutes of server time)
X-SignatureHMAC-SHA256 hex of <timestamp>.<raw JSON body>, keyed with your Sign Key

The signature is computed over the exact request body bytes you send. Build the JSON once and sign that exact string.

Node.js example

import crypto from "node:crypto";

const MERCHANT_ID = "ACME_CORP_AB12";
const SIGN_KEY = process.env.PAYNXT_SIGN_KEY;        // keep secret

const body = JSON.stringify({
  merchant_order_id: "ORD-1001",
  amount: 249900,                                     // smallest currency unit (paise)
  currency: "INR",
  customer: { name: "Priya", email: "priya@store.in", phone: "9000000000" },
  return_url: "https://yourstore.in/payment/return"
});

const timestamp = Date.now().toString();
const signature = crypto
  .createHmac("sha256", SIGN_KEY)
  .update(timestamp + "." + body)
  .digest("hex");

const res = await fetch("https://paynxt.xyz/v1/payment-sessions", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-Merchant-Id": MERCHANT_ID,
    "X-Timestamp": timestamp,
    "X-Signature": signature
  },
  body
});
const data = await res.json();
// redirect the customer to data.checkout_url

cURL example

TS=$(date +%s000)
BODY='{"merchant_order_id":"ORD-1001","amount":249900,"currency":"INR","customer":{"name":"Priya","email":"priya@store.in","phone":"9000000000"},"return_url":"https://yourstore.in/return"}'
SIG=$(printf '%s' "$TS.$BODY" | openssl dgst -sha256 -hmac "$PAYNXT_SIGN_KEY" | awk '{print $2}')

curl -X POST https://paynxt.xyz/v1/payment-sessions \
  -H "Content-Type: application/json" \
  -H "X-Merchant-Id: ACME_CORP_AB12" \
  -H "X-Timestamp: $TS" \
  -H "X-Signature: $SIG" \
  -d "$BODY"

Create a payment session

POST /v1/payment-sessions (signed). Request body:

FieldTypeNotes
merchant_order_idstringYour unique order reference
amountintegerSmallest currency unit (e.g. paise)
currencystringDefaults to INR
customer.namestringCustomer name
customer.emailstringCustomer email
customer.phonestringCustomer phone
descriptionstringOptional
return_urlstring (URL)Where the customer returns after payment

Response 201:

{
  "payment_session_id": "ps_xxxxxxxxxxxxxxxx",
  "checkout_url": "https://paynxt.xyz/checkout/ps_xxxxxxxxxxxxxxxx",
  "status": "created"
}

Checkout & redirect

Redirect the customer's browser to checkout_url. PayNXT renders the hosted checkout and processes payment through the configured gateway. After payment the customer is returned to your return_url.

Callbacks & webhooks

After payment, the customer is redirected to your return_url. For reliable server-side confirmation, set your Merchant webhook URL (your PayNXT admin sets this) — PayNXT will POST a signed event to it when a payment is captured.

Payload (POST, JSON)

{
  "event": "payment.captured",
  "payment_session_id": "ps_xxxxxxxxxxxxxxxx",
  "merchant_order_id": "ORD-1001",
  "amount": 100,                 // smallest unit (paise)
  "currency": "INR",
  "status": "captured",
  "gateway_payment_id": "pay_xxxxxxxxxxxx",
  "timestamp": "2026-06-27T08:00:00.000Z"
}

Verifying the signature

Header X-PayNXT-Signature = HMAC_SHA256(your_sign_key, raw_request_body) as hex. Recompute it over the exact body received and compare before trusting the event.

// Node example (Express, raw body)
const expected = crypto.createHmac("sha256", SIGN_KEY).update(rawBody).digest("hex");
if (expected !== req.header("X-PayNXT-Signature")) return res.status(401).end();
// mark merchant_order_id as paid

Respond 2xx to acknowledge. Treat the webhook as the source of truth for final status.

Error reference

HTTPMeaning
400Invalid request body (see details)
401Missing/invalid signature, unknown merchant, or stale timestamp
403Merchant not approved for transactions
404Resource not found

Go-live checklist

Questions? hello@paynxt.xyz