Developer Integration Reference
Welcome to the official PayxMint API documentation. Use this reference to integrate high-fidelity UPI automated payments securely into your core applications.
Simulate successful payment state transitions during development by sending an incoming POST request to the simulation endpoint using your active order_id.
API Environment, Auth & Idempotency
Authenticate all requests by including your secret API key in the Authorization header.
https://payxmint.com/api/v1
Authorization: Bearer YOUR_API_KEYIdempotency Keys
Pass an Idempotency-Key: <UUID> header on POST /create-intent to prevent duplicate payments during retries.
API Rate Limits
- Create Intent: 1,000 TPS (60,000 req/min)
- Check Status: 2,000 TPS (120,000 req/min)
Exceeded requests return HTTP 429 Too Many Requests with a Retry-After header.
Standard API Error Response
All error responses return standard HTTP status codes (400, 401, 404, 429, 500) with a structured error object:
{
"error": {
"type": "invalid_request_error",
"code": "authentication_failed",
"message": "Missing or invalid API key in Authorization header."
}
}Collections & Inbound Payments
1. Initiate Payment (/create-intent)
Creates a new dynamic payment intent and returns the checkout URL to showcase to your user, alongside high-fidelity raw UPI deep links.
Endpoint URL
Request Body Payload
| Field | Type | Status |
|---|---|---|
| amount | string/number | Required |
| order_id | string | Optional (Alphanumeric, >= 8 chars) |
| customer_mobile | string | Optional |
| customer_email | string | Optional |
| customer_ip | string | Optional |
| customer_device_id | string | Optional |
| redirect_url | string | Optional |
| gateway | string | Optional (PAYTM, GPAY, PHONEPE, PINELABS) |
| metadata | object | Optional |
Interactive Request
curl --request POST \
--url https://payxmint.com/api/v1/create-intent \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"amount": "5000.00",
"order_id": "pay_202506038627",
"customer_mobile": "9898989898",
"customer_email": "amit_bansal@email.com",
"redirect_url": "https://merchant.site/thankyou",
"customer_ip": "192.168.1.1",
"customer_device_id": "dev_xyz123",
"gateway": "GPAY",
"metadata": {
"cart_id": "12345"
}
}'Sample Response
{
"id": "ptx_8f2a9c3d1e",
"object": "payment_intent",
"amount": 1850.00,
"currency": "INR",
"status": "PENDING",
"order_id": "tx_873491023",
"checkout_url": "https://payxmint.com/pay/ptx_8f2a9c3d1e",
"payment_token": "ptx_8f2a9c3d1e",
"upi_link": "upi://pay?pa=merchant@upi&pn=PayxMint...",
"upi_links": {
"upi": "upi://pay?pa=merchant@upi...",
"gpay": "intent://...",
"phonepe": "phonepe://...",
"paytm": "paytmmp://..."
},
"qr_data": "upi://pay?pa=merchant@upi...",
"metadata": {},
"created": 1779187312
}2. Payment Status (/check-status)
Queries and retrieves the exact transaction metadata, settlement details, and collection status using your order_id.
Endpoint URL
Request Body Payload
| Field | Type | Status |
|---|---|---|
| order_id | string | Required (Unique Merchant ID) |
GET to check status by appending order_id to search params: https://payxmint.com/api/v1/check-status?order_id=pay_202506038627Interactive Request
curl --request POST \
--url https://payxmint.com/api/v1/check-status \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"order_id": "pay_202506038627"
}'Sample Response
{
"id": "ptx_8f2a9c3d1e",
"object": "payment_intent",
"amount": 1850.00,
"currency": "INR",
"status": "SUCCESS",
"order_id": "tx_873491023",
"metadata": {},
"payer": {
"name": "John Doe",
"upi": "johndoe@ybl"
},
"settlement": {
"utr": "6120948375",
"txn_id": "tx_612093847",
"timestamp": "2026-05-19T17:11:45.000Z"
},
"created": 1779187312,
"expire_at": 1779188212
}3. Process Webhook Data (Payment)
To guarantee secure event delivery, calculate the HMAC-SHA256 hex signature directly from the raw incoming body string against your webhook secret.
Payment systems operate under at-least-once delivery guarantees. Due to network retries, automated reconciliation reconcilers, or concurrent worker dispatches, your server may receive the same payment.success webhook multiple times.
order_id is already marked as SUCCESS or CREDITED, do NOT credit the user again. Simply return HTTP 200.UNIQUE constraint on order_id / utr in your payments table to make duplicate credit inserts physically impossible.BEGIN ... COMMIT) or acquire a Redis lock on lock:order:{order_id} for 10 seconds.200 OK response after processing (even on duplicate events) so PayxMint knows the event was delivered and halts retries.Cryptographic Headers
Verification Implementation (NodeJS)
const crypto = require('crypto');
// 1. Webhook Secret from your PayxMint Dashboard
const webhookSecret = process.env.PAYXMINT_WEBHOOK_SECRET;
function handleIncomingWebhook(req, res) {
const signature = req.headers['x-payxmint-signature'];
const rawBody = req.rawBody; // Ensure raw unparsed string body
// 2. Validate HMAC-SHA256 signature
const expectedSignature = crypto
.createHmac('sha256', webhookSecret)
.update(rawBody)
.digest('hex');
if (signature !== expectedSignature) {
return res.status(401).json({ error: 'Invalid signature' });
}
const payload = JSON.parse(rawBody);
const { order_id, amount, utr } = payload;
// 3. IDEMPOTENCY SAFETY NET: Check if order was already processed
const order = await db.orders.findOne({ order_id });
if (!order || order.status === 'SUCCESS') {
// Already credited or processed! Acknowledge with 200 OK and EXIT safely.
return res.status(200).json({ status: 'already_processed' });
}
// 4. Atomic Credit within Database Transaction
await db.transaction(async (tx) => {
await tx.orders.update({ where: { order_id }, data: { status: 'SUCCESS', utr } });
await tx.wallets.increment({ where: { userId: order.userId }, data: { balance: amount } });
});
return res.status(200).json({ status: 'success' });
}Sample Webhook Notification Payload
{
"event": "payment.success",
"status": "SUCCESS",
"order_id": "pay_202506038627",
"amount": 620.00,
"utr": "7019283745",
"payer_name": "John Doe",
"payer_upi": "johndoe@ybl",
"metadata": {},
"timestamp": "2026-05-19T17:11:45.000Z"
}4. White-label / Custom Checkout Integration Flow
If you wish to host your own checkout page and retain full control over the user interface, you can use PayxMint as a headless payment engine. This avoids redirecting the user to our hosted checkout_url.
Server calls create-intent and extracts upi_links & qr_data.
Render UPI app buttons for mobile or a high-res QR code on desktop.
Poll check-status every 3-4s to update UI and redirect.
Securely fulfill the order upon verified server-to-server webhook.
Initialize Payment Session from Backend
Call POST /api/v1/create-intent from your backend server. Extract the upi_links and qr_data strings and return them to your client application:
const response = await fetch("https://payxmint.com/api/v1/create-intent", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Idempotency-Key": "order_" + Date.now(),
"Content-Type": "application/json"
},
body: JSON.stringify({
amount: 1000.50,
order_id: "ORDER_" + Date.now(),
redirect_url: "https://yourwebsite.com/payment/success"
})
});
const intentData = await response.json();
// Pass intentData.upi_links and intentData.qr_data to your frontendMobile Devices (Deep Links)
On mobile devices, render buttons that open installed UPI applications directly using the URLs provided in the upi_links object:
💡 Note: UPI deep links are returned dynamically by the API. Never hardcode static UPI handles.
Desktop Devices (QR Code)
On desktop, render a high-contrast QR code using qrcode.react from the raw qr_data string:
import React from 'react';
import { QRCodeSVG } from 'qrcode.react';
export default function DesktopQRCode({ qrData, amount }) {
return (
<div className="p-6 border border-slate-200 rounded-2xl text-center">
<h3 className="text-sm font-bold text-slate-800 mb-2">Scan to Pay: ₹${amount}</h3>
<div className="flex justify-center my-4">
<QRCodeSVG value={qrData} size={220} includeMargin={true} />
</div>
<p className="text-xs text-slate-400 font-medium">
Scan with Google Pay, PhonePe, Paytm, or BHIM
</p>
</div>
);
}Real-Time UI Status Updates (Polling)
While the user completes the payment on their phone, poll the check-status endpoint every 3 to 4 seconds to transition the UI instantly:
import React, { useEffect, useState } from 'react';
export default function CustomCheckoutPage({ orderId }) {
const [status, setStatus] = useState("PENDING");
useEffect(() => {
if (status !== "PENDING") return; // Stop polling when completed
const interval = setInterval(async () => {
try {
// In production, proxy through your backend or call check-status directly
const response = await fetch(`https://payxmint.com/api/v1/check-status?order_id=${orderId}`, {
headers: { "Authorization": "Bearer YOUR_API_KEY" }
});
const data = await response.json();
if (data.status === "SUCCESS") {
setStatus("SUCCESS");
clearInterval(interval);
// Redirect user or show success UI
window.location.href = "/checkout/success?order_id=" + orderId;
} else if (data.status === "EXPIRED") {
setStatus("EXPIRED");
clearInterval(interval);
}
} catch (err) {
console.error("Polling error:", err);
}
}, 3500); // Check every 3.5 seconds
return () => clearInterval(interval); // Cleanup on unmount
}, [orderId, status]);
if (status === "SUCCESS") return <div className="text-emerald-600 font-bold">Payment Successful! Redirecting...</div>;
if (status === "EXPIRED") return <div className="text-rose-600 font-bold">Payment Expired. Please retry.</div>;
return <div className="text-slate-600">Waiting for payment scan...</div>;
}5. Google Pay Native Intent Flow (Web & Mobile Apps)
Deliver a seamless, high-conversion payment flow for Google Pay users on Android devices using native intent image sharing. This opens the Google Pay payment interface directly from your web or mobile app with full device compatibility.
A. Web Custom Checkout (React / Next.js / Vue / Vanilla JS)
Convert the qr_data Data URI into a synchronous File on page load to preserve Transient User Activation, then trigger navigator.share() on button click:
// 1. Helper: Convert base64 dataURI to File synchronously
function dataURItoFile(dataURI, filename) {
const arr = dataURI.split(',');
const mime = arr[0].match(/:(.*?);/)[1];
const bstr = atob(arr[1]);
let n = bstr.length;
const u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, { type: mime });
}
// 2. Click Handler: Trigger Native Share Sheet on Android
async function handleGooglePayClick(qrDataUrl) {
try {
const paymentFile = dataURItoFile(qrDataUrl, 'payxmint_payment_card.png');
// Check if browser supports sharing image files
if (navigator.canShare && navigator.canShare({ files: [paymentFile] })) {
await navigator.share({
files: [paymentFile],
title: 'Pay with Google Pay'
});
} else {
// Fallback for desktop browsers & restricted in-app WebViews (Instagram/Telegram)
openOnScreenQrModal(qrDataUrl);
}
} catch (err) {
if (err.name !== 'AbortError') {
openOnScreenQrModal(qrDataUrl);
}
}
}React Native
Using react-native-share
import Share from 'react-native-share';
async function openGPay(qrBase64) {
await Share.open({
url: qrBase64,
type: 'image/png',
title: 'Pay with Google Pay',
failOnCancel: false,
});
}Flutter
Using share_plus
import 'package:share_plus/share_plus.dart';
void shareToGPay(String filePath) {
Share.shareXFiles(
[XFile(filePath)],
text: 'Pay with Google Pay',
);
}Android Native (Kotlin)
Using Intent.ACTION_SEND
val intent = Intent(Intent.ACTION_SEND).apply {
type = "image/png"
putExtra(Intent.EXTRA_STREAM, qrFileUri)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
startActivity(Intent.createChooser(intent, "Pay with Google Pay"))💡 Card Image Aspect Ratio Best Practice (Universal 5:4 Standard)
Different Android phone models format their share sheet thumbnails differently (Samsung uses a 1:1 box; Xiaomi & Vivo use a 4:3 card; Pixel uses a 16:9 banner). Rendering your payment voucher card in a 5:4 aspect ratio (1000 × 800px) with an 85% central safe zone guarantees that your brand, amount, and QR code stay large, crisp, and never get cropped across any phone.
6. Webhook Event Logs (/events)
Query past webhook delivery attempts, inspect payloads, and audit failed or retried notifications for reconciliation.
Endpoint URL & Query Params
Interactive Request
curl --request GET \ --url 'https://payxmint.com/api/v1/events?limit=10&offset=0' \ --header 'Authorization: Bearer YOUR_API_KEY'
Sample Response
{
"object": "list",
"url": "/v1/events",
"has_more": false,
"data": [
{
"id": "evt_8f1a2b3c4d",
"object": "event",
"type": "payment.success",
"created": 1779187320,
"data": {
"event": "payment.success",
"order_id": "pay_202506038627",
"amount": 5000.00,
"utr": "7019283745"
},
"status": "DELIVERED",
"retry_count": 0,
"next_retry": null
}
]
}7. eCommerce Plugins
We provide ready-to-use plugins for major eCommerce platforms. Integrate PayxMinT in minutes without writing a single line of code.
WooCommerce / WordPress
Full Gateway Integration
- Download the official WooCommerce plugin
- Upload via Plugins → Add New in WordPress
- Activate PayxMint Payment Gateway
- Enter your Merchant ID and API Keys in Settings
Shopify AppComing Soon
Offsite Payment Gateway
Due to strict Shopify Partner regulations, a direct zip installation is not possible. We are currently getting our official App approved on the Shopify App Store.