KlyroPay API Documentation

Integrate PayIn and Payout services into your application

Base URL: https://admin.klyropay.com/api

Authentication

All API requests require an API key in the request header.

Required Headers

X-Api-Key: your_api_key
Content-Type: application/json
⚠️ IP Whitelist Required
Your server IP must be whitelisted before making API calls. Submit your IP and callback URL via the dashboard. Admin approval required.

Authentication Flow

Request → Check API Key → Check IP Whitelist → Check Rate Limit → Process

PayIn

Collect UPI payments from your customers. Supports GPay, PhonePe, Paytm, BHIM and all UPI apps.

Create PayIn → Get intent_url → Show QR / Redirect customer → Customer pays → Webhook → Wallet credited
Wallet Credit: Customer pays ₹1,000 → Commission ₹10 → Your wallet receives ₹990
Expiry: Payment link expires in 10 minutes. Unpaid transactions are auto-marked as expired.

1. Create PayIn

POST /api/v1/payin/create

Request Body

{
    "order_id":       "YOUR-ORDER-001",
    "amount":         1000,
    "customer_phone": "9876543210",
    "customer_name":  "Rahul Sharma"
}
FieldTypeRequiredDescription
order_idstringOptionalYour unique order ID (max 100 chars). Auto-generated if not provided.
amountnumberRequiredCollection amount in ₹ — minimum ₹300
customer_phonestringRequiredCustomer's 10-digit mobile number
customer_namestringOptionalCustomer name (max 100 chars)

Response — 201

{
    "success": true,
    "data": {
        "transaction_id": "txn_xxxxxxxxxxxxxxxx",
        "order_id":       "YOUR-ORDER-001",
        "txn_ref":        "PAYIN-REF-XXXXX",
        "amount":         1000.00,
        "commission":     10.00,
        "intent_url":     "upi://pay?pa=xxxxx&am=1000.00&cu=INR",
        "expires_in":     600,
        "status":         "pending"
    }
}
FieldDescription
transaction_idSave this — used for status checks
intent_urlUPI payment link — generate QR or redirect mobile users
expires_inSeconds until expiry (600 = 10 minutes)
commissionYour service charge — deducted from credited amount

Showing the Payment to Customer

QR Code (Desktop)
<script src="https://cdnjs.cloudflare.com/ajax/libs/
qrcodejs/1.0.0/qrcode.min.js"></script>

<div id="qrcode"></div>
<input type="hidden" id="upi-url"
    value="{{ $intentUrl }}">

<script>
new QRCode(document.getElementById('qrcode'), {
    text: document.getElementById('upi-url').value,
    width: 220, height: 220
});
</script>
UPI Button (Mobile)
<!-- Pass via hidden input to avoid
     HTML encoding issues -->
<input type="hidden" id="upi-url"
    value="{{ $intentUrl }}">

<button onclick="
    window.location.href =
    document.getElementById('upi-url').value
">
    Pay with UPI App
</button>

2. Check Payment Status

GET /api/v1/payin/status/{txn_ref}
{
    "success": true,
    "data": {
        "transaction_id": "txn_xxxxxxxxxxxxxxxx",
        "order_id":       "YOUR-ORDER-001",
        "txn_ref":        "PAYIN-REF-XXXXX",
        "amount":         1000.00,
        "commission":     10.00,
        "utr":            "407241812279",
        "status":         "success",
        "created_at":     "2024-04-30T10:00:00.000000Z"
    }
}
StatusMeaning
pendingAwaiting customer payment
successPayment received — wallet credited
failedPayment failed
expired10 minutes passed without payment

3. Transaction History

GET /api/v1/payin/transactions
ParamDescriptionDefault
pagePage number1
limitRecords per page (max 100)15

Payout

Transfer money directly to any bank account via IMPS.

Create Payout → Wallet debited (amount + commission) → Bank transfer → Webhook on final status
Wallet Debit: Transfer ₹5,000 + Commission ₹10 = ₹5,010 debited from wallet
Refund: If transfer fails, full amount is automatically refunded to wallet.

1. Initiate Payout

POST /api/v1/services/payout/process

Request Body

{
    "mobile_no":          "9876543210",
    "beneficiary_name":   "Rahul Sharma",
    "account_no":         "1234567890",
    "ifsc":               "SBIN0001234",
    "bank_name":          "State Bank of India",
    "amount":             5000,
    "transfer_type":      "5",
    "partner_request_id": "YOUR-UNIQUE-ORDER-ID"
}
FieldTypeRequiredDescription
mobile_nostringRequired10-digit mobile number
beneficiary_namestringRequiredAccount holder name (max 100 chars)
account_nostringRequiredBank account number (8–20 digits)
ifscstringRequiredIFSC code — format: ABCD0123456
bank_namestringRequiredBank name (max 100 chars)
amountnumberRequiredTransfer amount in ₹ (min ₹1,000 — max ₹2,00,000)
transfer_typestringRequiredAlways "5" (IMPS)
partner_request_idstringOptionalYour unique order ID. Auto-generated if not sent. Used for duplicate prevention.

Response — Success

{
    "success": true,
    "message": "Payout transferred successfully.",
    "data": {
        "transaction": {
            "transaction_id":     "txn_xxxxxxxxxxxxxxxx",
            "reference_id":       "bank_reference_number",
            "partner_request_id": "YOUR-UNIQUE-ORDER-ID",
            "status":             "success",
            "amount":             5000.00,
            "charge":             10.00,
            "net_amount":         5010.00
        }
    }
}

Response — Pending

{
    "success": true,
    "message": "Payout is being processed. You will be notified once settled.",
    "data": {
        "transaction": {
            "status":  "pending",
            "amount":  5000.00,
            "charge":  10.00,
            "net_amount": 5010.00
        }
    }
}
StatusMeaning
successMoney credited to beneficiary
pendingBank processing — callback will follow
failedTransfer failed
refundedTransfer failed — amount refunded to wallet

2. Transaction History

GET /api/v1/transactions/service/payout
ParamDescriptionDefault
statusFilter: success / pending / failed / refundedAll
from_dateStart date — YYYY-MM-DD
to_dateEnd date — YYYY-MM-DD
pagePage number1
limitRecords per page (max 100)15

3. Single Transaction

GET /api/v1/transactions/service/payout/{transaction_id}

Wallet

Check your wallet balance and transaction history.

Balance

GET /api/v1/wallet/balance
{
    "success": true,
    "data": {
        "balance":        45000.00,
        "locked_balance": 0.00
    }
}
FieldDescription
balanceAvailable balance — usable for payouts
locked_balanceOn-hold amount — not available for use

Callback (Webhook)

KlyroPay sends a POST request to your registered callback URL when a transaction reaches a final status.

Important: Callbacks are sent only on success, failed, refunded, and expired — not on pending.
Retry: 5 attempts with 5-minute gaps if your server doesn't return HTTP 200.

Callback Request

POST https://yourserver.com/your-callback-endpoint
Content-Type: application/json
X-KlyroPay-Event: transaction.updated
X-KlyroPay-Signature: hmac_sha256_signature

PayIn Callback Payload

{
    "event":          "transaction.updated",
    "transaction_id": "txn_xxxxxxxxxxxxxxxx",
    "service":        "payin",
    "status":         "success",
    "amount":         1000.00,
    "commission":     10.00,
    "net_amount":     990.00,
    "order_id":       "YOUR-ORDER-001",
    "txn_ref":        "PAYIN-REF-XXXXX",
    "utr":            "407241812279",
    "timestamp":      "2024-04-30T10:05:00.000000Z"
}

Payout Callback Payload

{
    "event":              "transaction.updated",
    "transaction_id":     "txn_xxxxxxxxxxxxxxxx",
    "service":            "payout",
    "status":             "success",
    "amount":             5000.00,
    "commission":         10.00,
    "net_amount":         5010.00,
    "reference_id":       "bank_ref_number",
    "partner_request_id": "YOUR-ORDER-ID",
    "timestamp":          "2024-04-16T10:30:00.000000Z"
}

Verify Signature

Always verify the signature to ensure the callback is from KlyroPay.

PHP
$sig      = $_SERVER['HTTP_X_KLYROPAY_SIGNATURE'];
$payload  = json_decode(
    file_get_contents('php://input'), true
);
$expected = hash_hmac(
    'sha256',
    json_encode($payload),
    'YOUR_API_KEY'
);

if (!hash_equals($expected, $sig)) {
    http_response_code(401);
    exit;
}

// Valid — process the callback
http_response_code(200);
echo json_encode(['status' => 'ok']);
Node.js
const crypto = require('crypto');

const sig = req.headers[
    'x-klyropay-signature'
];
const expected = crypto
    .createHmac('sha256', 'YOUR_API_KEY')
    .update(JSON.stringify(req.body))
    .digest('hex');

if (!crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(sig)
)) {
    return res.status(401).send('Unauthorized');
}

res.status(200).json({ status: 'ok' });

Error Reference

All error responses follow this format:

{ "success": false, "message": "Error description.", "data": null }
HTTP CodeMessageReason
401API key is missingX-Api-Key header not sent
401Invalid API keyKey is incorrect
401API key is inactive or expiredKey revoked or expired
403No IP whitelist configuredNo IP approved yet
403Your IP is not whitelistedRequest from non-whitelisted IP
403You do not have access to this serviceService not assigned to your account
409Duplicate requestpartner_request_id already exists
422Validation failedInvalid request fields
422Insufficient wallet balanceNot enough balance for payout
429Rate limit exceededToo many requests per minute

Quick Reference

MethodEndpointDescription
POST/api/v1/payin/createCreate PayIn request
GET/api/v1/payin/status/{txn_ref}Check PayIn status
GET/api/v1/payin/transactionsPayIn history
POST/api/v1/services/payout/processInitiate payout
GET/api/v1/transactions/service/payoutPayout history
GET/api/v1/transactions/service/payout/{id}Single payout detail
GET/api/v1/wallet/balanceWallet balance