Quickstart Integration
Integrate real-time UPI payments into your application in three simple steps:
Sign up and grab your sec_live_... API key from the Dashboard.
Call POST /api/v1/orders and redirect your user to the generated checkout_url.
Listen for payment.succeeded webhook on your server with HMAC verification.
Authentication
All REST API requests require your merchant API key passed via the Authorization header or x-api-key header.
Authorization: Bearer sec_live_YOUR_MERCHANT_KEYCreate Payment Order
| PARAMETER | TYPE | REQUIRED | DESCRIPTION |
|---|---|---|---|
| amount | number | Yes | The integer or decimal order amount in INR (e.g. 499.00) |
| coupon_code | string | No | Optional discount coupon (e.g. "SAVE20", "FLAT50") automatically validated and deducted |
| customer_name | string | No | Payer's full name |
| customer_email | string | No | Payer's email address for notifications |
| customer_phone | string | No | 10-digit mobile number |
| callback_url | string | No | Redirect destination after customer completes payment |
| webhook_url | string | No | Override default webhook destination for this specific order |
| metadata | object | No | Arbitrary key-value JSON stored and returned with webhooks |
import axios from 'axios';
// 1. Initiate Payment Order
export async function createPaymentOrder() {
const res = await axios.post(
'https://payments.fluxbasedb.me/api/v1/orders',
{
amount: 499.00,
customer_name: 'Rajesh Kumar',
customer_email: 'rajesh@example.com',
customer_phone: '9876543210',
callback_url: 'https://yourapp.com/checkout/success',
webhook_url: 'https://yourapp.com/api/webhooks/fluxpay',
metadata: {
userId: 'usr_94812',
cartId: 'cart_0982'
}
},
{
headers: {
'Authorization': `Bearer ${process.env.FLUXPAY_API_KEY}`,
'Content-Type': 'application/json'
}
}
);
const { order_id, checkout_url } = res.data;
// 2. Redirect user or render embedded checkout
console.log('Order created:', order_id);
return checkout_url; // e.g. https://payments.fluxbasedb.me/pay/ord_xxxx
}{
"success": true,
"order_id": "ord_8f921b7c",
"order": {
"id": "ord_8f921b7c",
"amount": 499,
"final_amount": 499.14,
"vpa": "sumith0909@ibl",
"status": "pending",
"expires_at": "2026-09-09T01:30:00.000Z"
},
"checkout_url": "https://payments.fluxbasedb.me/pay/ord_8f921b7c"
}Checking Order Status
You can query the order state on-demand or subscribe to live server-sent events (SSE).
Returns the latest order JSON with status: pending, paid, or expired.
Standard EventSource stream that emits payment confirmation the exact millisecond the bank SMS reconciles.
Outbound Webhooks
When an order is successfully matched, FluxPay dispatches an automated HTTP POST request to your webhook URL.
{
"event": "payment.succeeded",
"order_id": "ord_8f921b7c",
"amount": 499.14,
"base_amount": 499.00,
"utr": "625374829102",
"paid_at": "2026-09-09T01:25:34.000Z",
"customer": {
"name": "Rajesh Kumar",
"email": "rajesh@example.com",
"phone": "9876543210"
},
"metadata": {
"user_id": "usr_94812"
}
}Verifying Webhook Signatures
FluxPay includes the X-FluxPay-Signature header with every webhook delivery in the format t=timestamp,v1=signature. Always verify this signature on your server before trusting the event.
import crypto from 'crypto';
// Next.js App Router Webhook Route: src/app/api/webhooks/fluxpay/route.ts
export async function POST(req: Request) {
const rawBody = await req.text();
const signatureHeader = req.headers.get('x-fluxpay-signature') || '';
// Parse header: "t=1725839000,v1=abc123hash..."
const parts = Object.fromEntries(
signatureHeader.split(',').map(kv => kv.split('='))
);
const timestamp = parts['t'];
const expectedSig = parts['v1'];
const secret = process.env.FLUXPAY_WEBHOOK_SECRET!; // From dashboard Settings
// Compute expected HMAC SHA-256
const signedPayload = `${timestamp}.${rawBody}`;
const computedSig = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
if (computedSig !== expectedSig) {
return new Response('Invalid webhook signature', { status: 400 });
}
const event = JSON.parse(rawBody);
if (event.event === 'payment.succeeded') {
const { order_id, amount, utr, metadata } = event;
console.log(`Order ${order_id} PAID: ₹${amount} (UTR: ${utr})`);
// Unlock customer features or deliver order
// await db.fulfillOrder(metadata.userId);
}
return new Response(JSON.stringify({ received: true }), {
status: 200,
headers: { 'Content-Type': 'application/json' }
});
}import hmac
import hashlib
import json
from flask import Flask, request, jsonify
app = Flask(__name__)
WEBHOOK_SECRET = "whsec_your_secret_from_settings"
@app.route("/api/webhooks/fluxpay", methods=["POST"])
def fluxpay_webhook():
raw_body = request.get_data(as_text=True)
signature_header = request.headers.get("X-FluxPay-Signature", "")
# Parse header: "t=1725839000,v1=hash..."
parts = dict(item.split("=") for item in signature_header.split(",") if "=" in item)
timestamp = parts.get("t", "")
expected_sig = parts.get("v1", "")
# Compute HMAC SHA-256
signed_payload = f"{timestamp}.{raw_body}".encode("utf-8")
computed_sig = hmac.new(
WEBHOOK_SECRET.encode("utf-8"),
signed_payload,
hashlib.sha256
).hexdigest()
if computed_sig != expected_sig:
return "Invalid signature", 400
data = json.loads(raw_body)
if data.get("event") == "payment.succeeded":
order_id = data.get("order_id")
amount = data.get("amount")
utr = data.get("utr")
print(f"Payment received for order {order_id}: ₹{amount}, UTR: {utr}")
return jsonify({"received": True}), 200