API

Authenticate with a merchant secret: Authorization: Bearer sk_live_…. Secrets are hashed at rest and shown once. Keep them on your server — never in HTML, apps, or mobile clients.

Download SDK Browser widget

Easiest path

  1. Your server creates an order (secret key).
  2. Send the customer to payment_url (or iframe embed_url) — same Pay → I PAID → UTR UI.
  3. Listen for SUCCESS via status_url or the signed webhook.

Create order

curl -X POST https://pay.afly.in/api/v1/orders \
  -H "Authorization: Bearer sk_live_xxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: ord-10291" \
  -d '{"amount":"1500.00","merchant_order_id":"ORD-10291","customer_name":"A. Kabir"}'

Verify payment

Prefer hosted checkout. If you verify from your server, send only the UPI reference. A UTR that was already claimed returns ref_already_claimed — “This UTR is already used.”

curl -X POST https://pay.afly.in/api/v1/payments/verify \
  -H "Authorization: Bearer sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"order_id":"ORD-AB12CD","upi_ref":"129211813480"}'

Create-order also returns upi_uri (amount locked), payment_url, embed_url (iframe), and status_url.

Server SDK

<?php
require "voltpay.php";
$vp = new VoltPay("https://pay.afly.in", getenv("VOLTPAY_SECRET"));
$order = $vp->createOrder(["amount" => "10.00", "merchant_order_id" => "SKU-10"], "SKU-10");
header("Location: " . $order["payment_url"]);

Payment status

curl https://pay.afly.in/api/v1/orders/ORD-AB12CD \
  -H "Authorization: Bearer sk_live_xxx"

Webhook

On success VoltPay POSTs JSON to your URL with header X-VoltPay-Signature: t=TIMESTAMP,v1=HMAC_SHA256(secret, timestamp + '.' + body).

{
  "event": "payment.success",
  "data": {
    "order_id": "ORD-10291",
    "amount": "1500.00",
    "upi_ref": "129211813480",
    "status": "SUCCESS"
  }
}

cURL example

<?php
$ch = curl_init("https://pay.afly.in/api/v1/orders");
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_HTTPHEADER => [
    "Authorization: Bearer " . $secret,
    "Content-Type: application/json",
    "Idempotency-Key: " . $merchantOrderId,
  ],
  CURLOPT_POSTFIELDS => json_encode([
    "amount" => "1500.00",
    "merchant_order_id" => $merchantOrderId,
  ]),
  CURLOPT_RETURNTRANSFER => true,
]);
$order = json_decode(curl_exec($ch), true);
// Redirect customer to $order["data"]["payment_url"]

Device ingest

The Android listener sends the raw notification. The server parses it. Pair with a 6-digit code from the merchant dashboard, then:

POST https://pay.afly.in/api/v1/device/ingest
Authorization: Bearer dt_…
{"raw_message":"Rs. 1,500 received in Slice A/c xx4210 ... (Ref ID: 129211813480).","package":"slice"}