Pay AGL
Merchant REST API

Pay AGL API Documentation

Create payment links, collect UPI pay-ins, send bank payouts, check wallet balances, and receive signed webhooks from one merchant integration.

Quickstart for merchants

  1. Log in to the merchant dashboard.
  2. Open API & Webhooks and copy your live API key. Keep your API secret private; it is used to verify Pay AGL webhooks.
  3. Submit your server IP for approval in the IP whitelist section if your account uses whitelist enforcement.
  4. Configure pay-in and payout callback URLs.
  5. Use the examples below from your backend server, never from browser JavaScript.
Base URL: https://payagl.com. All request and response bodies are JSON. Amounts are decimal numbers in your merchant currency, usually INR for Indian UPI/IMPS rails.

Authentication

Send your live merchant API key on every API request.

x-api-key: pk_live_your_merchant_key
Content-Type: application/json
StatusMeaning
401Invalid API key.
403Merchant inactive, IP not whitelisted, or payout fee not configured.
429Rate limited.

POSTCreate payment

Creates a production pay-in through the active Pay AGL route and returns a hosted checkout URL plus PSP-issued UPI deeplinks. Pay AGL never returns a placeholder VPA. order_id is required and idempotent per merchant: retrying the exact same request returns the existing transaction; reusing it with different amount, currency, or destination returns 409. Callback and post-payment redirect URLs must use public https:// addresses. The request currency must match the merchant account currency.

curl -X POST https://payagl.com/api/payment/create \
  -H "x-api-key: pk_live_your_merchant_key" \
  -H "Content-Type: application/json" \
  -d '{
    "order_id": "ORD-10001",
    "amount": 1500.00,
    "currency": "INR",
    "customer_name": "Ramesh Kumar",
    "customer_email": "ramesh@example.com",
    "customer_phone": "9999999999",
    "description": "Order #10001",
    "callback_url": "https://merchant.example/webhooks/payin",
    "redirect_url_after": "https://merchant.example/thank-you"
  }'
{
  "txn_id": "TXN...",
  "order_id": "ORD-10001",
  "status": "PENDING",
  "amount": 1500,
  "currency": "INR",
  "redirect_url": "/api/payment/redirect/TXN...",
  "checkout_url": "/checkout.html?id=TXN...",
  "payment_links": {
    "ready": true,
    "upi_deeplink": "upi://pay?...",
    "phonepe_intent": "phonepe://pay?...",
    "gpay_intent": "tez://upi/pay?...",
    "paytm_intent": "paytmmp://pay?...",
    "qr_image_url": null,
    "expires_at": "2026-06-23T...",
    "error": null
  }
}

Hosted vs custom checkout

  • Hosted checkout: redirect the customer to checkout_url.
  • Custom checkout: open the correct value from payment_links for PhonePe, GPay, Paytm, or generic UPI.

GETPayment status

curl https://payagl.com/api/payment/status/TXN... \
  -H "x-api-key: pk_live_your_merchant_key"
{
  "txn_id": "TXN...",
  "order_id": "ORD-10001",
  "merchant_id": "PAGLMER000080",
  "amount": 1500,
  "currency": "INR",
  "status": "SUCCESS",
  "completed_at": 1782220000000
}

Payment statuses: PENDING, SUCCESS, FAILED.

GETWallet balance

Returns pay-in wallet and payout wallet balances. API payouts debit the payout wallet.

curl https://payagl.com/api/wallet/balance \
  -H "x-api-key: pk_live_your_merchant_key"
{
  "merchant_id": "PAGLMER000080",
  "currency": "INR",
  "payin_wallet": {
    "balance": 150000,
    "pending_settlement": 5000,
    "pending_topup": 0,
    "pending_total": 5000,
    "available": 145000
  },
  "payout_wallet": { "balance": 80000, "available": 80000 },
  "balance": 150000,
  "payout_wallet_balance": 80000,
  "available": 145000
}

POSTCreate API payout

Sends a bank payout (IMPS or NEFT) from your payout wallet to a beneficiary account. Your merchant account must have API payout commission configured. total_debit = amount + payout_commission. order_id is idempotent per merchant. The current platform minimum is 150; merchant and route limits may be stricter and are enforced at request time.

curl -X POST https://payagl.com/api/payout/create \
  -H "x-api-key: pk_live_your_merchant_key" \
  -H "Content-Type: application/json" \
  -d '{
    "order_id": "WD-10001",
    "amount": 500.00,
    "method": "IMPS",
    "beneficiary_name": "Ramesh Kumar",
    "account_number": "123456789012",
    "ifsc": "HDFC0001234",
    "callback_url": "https://merchant.example/webhooks/payout"
  }'

Required fields

FieldDescription
order_idYour required unique reference. Exact retries are idempotent; mismatched reuse returns 409.
amountPayout amount. Minimum 150.
beneficiary_nameAccount holder name.
account_numberBeneficiary bank account number.
ifscBeneficiary bank IFSC code.

Optional fields

FieldDescription
methodIMPS (default) or NEFT.
callback_urlOptional per-request payout webhook override. Must be a public https:// URL.
beneficiary_email, beneficiary_mobileBeneficiary contact details.
beneficiary_bank, beneficiary_branchBank and branch name/address.
beneficiary_address, beneficiary_pincodeBeneficiary address and pincode.
notePayout note/narration.
{
  "payout_id": "PAYOUT...",
  "order_id": "WD-10001",
  "merchant_id": "PAGLMER000080",
  "amount": 500,
  "status": "PROCESSING",
  "payout_commission": 10,
  "total_debit": 510,
  "provider_ref": "PAYOUT...",
  "utr": ""
}

Payouts return PROCESSING first; the final SUCCESS/FAILED state is delivered to your callback_url webhook (and reflected in Payout status). On failure, the full total_debit is refunded to your payout wallet.

GETPayout status

curl https://payagl.com/api/payout/status/PAYOUT... \
  -H "x-api-key: pk_live_your_merchant_key"
{
  "payout_id": "PAYOUT...",
  "order_id": "WD-10001",
  "status": "SUCCESS",
  "amount": 500,
  "payout_commission": 10,
  "total_debit": 510,
  "provider_ref": "PAYOUT...",
  "utr": "123456789012"
}

Payout statuses: PROCESSING, SUCCESS, FAILED.

Production routing and checkout

Recommended: Send customers to the returned checkout_url. Pay AGL selects the active processor and supplies only a real PSP-issued UPI URI. Processor names, credentials, routing rules, and internal callback domains are never exposed to customers.
  • Do not generate, cache, or substitute your own UPI VPA or QR code.
  • Treat PENDING as non-final. Credit an order only after SUCCESS from a signed webhook or the status API.
  • Use a unique order_id for every order. Retrying the same ID is idempotent.
  • Store amount, IDs, status, UTR, and webhook delivery ID for reconciliation.
  • Keep API keys server-side and whitelist only fixed production IP addresses.

Webhooks from Pay AGL

Pay AGL sends webhooks to your saved callback URL or the per-request callback_url. Verify the signature against the exact raw request body using your merchant API secret.

POST https://merchant.example/webhooks/payin
Content-Type: application/json
X-PayAGL-Signature: hex_hmac_sha256(api_secret, raw_body)
X-PayAGL-Event: payment.pending | payment.success | payment.failed
X-PayAGL-Delivery-Id: uuid

Payment webhook body

{
  "txn_id": "TXN...",
  "order_id": "ORD-10001",
  "merchant_id": "PAGLMER000080",
  "amount": 1500,
  "currency": "INR",
  "status": "SUCCESS",
  "gateway_ref": "...",
  "utr": "123456789012",
  "completed_at": 1782220000000
}

Payout webhook body

{
  "payout_id": "PAYOUT...",
  "order_id": "WD-10001",
  "merchant_id": "PAGLMER000080",
  "amount": 500,
  "status": "SUCCESS",
  "utr": "123456789012",
  "payout_commission": 10,
  "total_debit": 510,
  "completed_at": "2026-06-23T..."
}

Node.js verification

const crypto = require("crypto");

function verifyPayAGL(rawBody, signature, apiSecret) {
  const expected = crypto
    .createHmac("sha256", apiSecret)
    .update(rawBody)
    .digest("hex");
  return expected === signature;
}

POSTSupport tickets

Raise and track support tickets directly from your own dashboard or server using your API key. Tickets appear in the Pay AGL support console and our team replies there.

Create a ticket

curl -X POST https://payagl.com/api/support/tickets \
  -H "x-api-key: pk_live_your_merchant_key" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "Payout WD-10001 not credited",
    "category": "Payouts",
    "priority": "high",
    "related_txn": "WD-10001",
    "message": "Customer says the payout has not arrived after 2 hours."
  }'
{
  "ticket_id": "tk_ab12cd",
  "subject": "Payout WD-10001 not credited",
  "category": "Payouts",
  "priority": "high",
  "status": "open",
  "related_txn": "WD-10001",
  "created_at": "2026-06-25T...",
  "updated_at": "2026-06-25T...",
  "messages": [ { "by": "merchant", "at": "2026-06-25T...", "text": "Customer says..." } ]
}

Categories: General, Payments / Pay-in, Payouts, Settlements, API / Integration, KYC / Account, Dispute / Chargeback, Other. Priorities: low, normal, high, urgent.

GET List your tickets

curl "https://payagl.com/api/support/tickets?status=open" \
  -H "x-api-key: pk_live_your_merchant_key"

GET Fetch one ticket

curl https://payagl.com/api/support/tickets/tk_ab12cd \
  -H "x-api-key: pk_live_your_merchant_key"

Reply to a ticket

curl -X POST https://payagl.com/api/support/tickets/tk_ab12cd/reply \
  -H "x-api-key: pk_live_your_merchant_key" \
  -H "Content-Type: application/json" \
  -d '{ "message": "Any update on this?" }'

Ticket statuses: open, pending (awaiting your reply), resolved, closed. Each message has by = merchant or support. Internal staff notes are never returned.

Integration assistance: @payagll on Telegram.

Error responses

Typical error body:

{ "detail": "message or validation details" }
HTTPMeaning
400Bad request, insufficient balance, or invalid business state.
401Invalid API key.
403IP not whitelisted, merchant inactive, or payout fee not configured.
404Transaction or payout not found for this merchant.
409The same order_id was reused with different payment or payout details, or the request is already processing.
422Validation error, missing fields, invalid amount or IFSC.
429Rate limited.
502Upstream gateway rejected the payout/payment.
503No active payment route is available for the requested country, rail, or amount.