---
updatedAt: 2025-06-17T11:14:24.000Z
agentTools:
  projectIndex: https://developers.aeronpay.in/llms.txt
---

# QR Callback / Webhook

This page describes the HTTP callback (webhook) that Aeronpay sends to your server each time a static-QR UPI payment is processed. It explains the endpoint requirements, payload schema, security recommendations, and best-practice response handling.

# 📘 Aeronpay – Callback / Webhook Specification

*(Static UPI Collection – “upi” Event)*

***

<br />

## 1  Overview

| Item                                 | Value / Notes                                                                                                                                          |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Trigger**                          | Successful or failed UPI transaction generated from a static QR (event=`"upi"`).                                                                       |
| **Protocol & Method**                | `HTTPS` `POST` (JSON body, UTF-8).                                                                                                                     |
| **Content-Type**                     | `application/json`.                                                                                                                                    |
| **Retries**                          | If your server does **not** return HTTP `200` within 30 s, Aeronpay re-sends up to **3 attempts** with exponential back-off (5 min → 15 min → 45 min). |
| **IP Source** *(optional)*           | You may whitelist our IP ranges in your firewall (contact Support for the latest CIDRs).                                                               |
| **Signature Header** *(recommended)* | `X-Aeronpay-Signature: <HMAC-SHA256>` calculated on the raw body using the shared webhook secret.                                                      |

***

## 2  Endpoint Requirements

1. **Public HTTPS URL** – e.g. `https://merchant.example.com/api/aeronpay/webhook`.
2. **TLS 1.2+** with a valid CA-signed certificate.
3. Accept **`POST`** requests with JSON.
4. Parse the body without altering key order when validating the HMAC.
5. **Respond with HTTP`200`** (body optional) once the payload is fully validated and processed; otherwise return an error status (4xx) *only* for permanent failures.

***

## 3  Sample Payload

```json
{
  "event": "upi",
  "bank": "Yes Bank",
  "param": [],
  "response": {
    "status": 1,
    "amount": "10.00",
    "utr": "837799277927",
    "refid": "",
    "receiver_name": "RAKESH MITTAL",
    "receiver_vpa": "partner.merchantname@samplebank",
    "txnid": "PTM2947729848273",
    "upiRefId": "PTM2947729848273",
    "remarks": "PTM2947729848273",
    "PayerMobileNumber": "",
    "PayerVPA": "rakeshmittal@pidfc",
    "PayerName": "RAKESH MITTAL",
    "TransactionDateTime": "2025-06-17 16:14:14",
    "txnNote": "Your transaction is successful",
    "qr_refid": "PTM2947729848273",
    "merchant_tranid": "PTM2947729848273",
    "terminalId": "499274788277482",
    "merchantId": "499274788277482"
  }
}
```

> **Tip:** Treat all fields as **case-sensitive**. Your JSON parser should support arbitrary key order.

***

## 4  Field-by-Field Reference

| Path                                 | Type   | Description / Possible Values                                                  |
| ------------------------------------ | ------ | ------------------------------------------------------------------------------ |
| `event`                              | string | Always `"upi"` for static-QR UPI payments.                                     |
| `bank`                               | string | Acquiring/settling bank for this transaction.                                  |
| `param`                              | array  | Reserved for future use (currently empty).                                     |
| `response.status`                    | number | `1` = Success  `0` = Pending/Processing  `-1` = Failed.                        |
| `response.amount`                    | string | Transaction amount (2-decimal string).                                         |
| `response.utr`                       | string | 12-digit UPI Unique Transaction Reference number.                              |
| `response.receiver_name`             | string | Merchant (payee) name.                                                         |
| `response.receiver_vpa`              | string | Merchant VPA.                                                                  |
| `response.txnid` / `upiRefId`        | string | Aeronpay transaction reference; always identical in static-QR flow.            |
| `response.remarks` / `txnNote`       | string | Transaction narrative shown to payer.                                          |
| `response.qr_refid`                  | string | Reference ID tied to the QR that initiated the payment.                        |
| `response.merchant_tranid`           | string | Merchant-supplied reference if provided during creation (else equals `txnid`). |
| `response.PayerVPA` / `PayerName`    | string | Payer’s UPI ID / name (may be empty if masked by bank).                        |
| `response.PayerMobileNumber`         | string | Payer’s mobile (may be empty/null).                                            |
| `response.TransactionDateTime`       | string | Settlement timestamp in `YYYY-MM-DD HH:MM:SS` (IST).                           |
| `response.terminalId` / `merchantId` | string | Bank-assigned terminal and merchant identifiers.                               |

***

## 5  Security & Signature Verification (Recommended)

1. **Webhook Secret** – generate & store a secret key in the Aeronpay Dashboard.

2. **Signature** – Aeronpay calculates:

   ```
   signature = HMAC_SHA256(secret, raw_request_body)
   ```

3. **Header** – `X-Aeronpay-Signature: <signature>` is added to the request.

4. **Validation Steps (Server-side)**

   * Read the raw body **verbatim**.
   * Re-compute the HMAC using your stored secret.
   * **Timing-safe compare** with the header value.
   * Reject the request (HTTP 400) if the signature mismatches.

***

## 6  Idempotency & Deduplication

* **txnid** is globally unique.
* Store each incoming `txnid` and short-circuit processing if you receive the same ID again (possible on retries).

***

## 7  Expected Response from Your Server

| Scenario                                | You should return                                      |
| --------------------------------------- | ------------------------------------------------------ |
| **Valid & processed successfully**      | HTTP `200 OK` (optionally: `{ "status":"received" }`). |
| Temporary server error / cannot process | HTTP `500` or `503` – will trigger retry (max 3).      |
| Invalid payload / signature mismatch    | HTTP `400` – **no** retries (permanent failure).       |

***

## 8  Testing the Webhook

1. In **Sandbox/Demo** mode, trigger a test payment via the dashboard or API.
2. Inspect your server logs to confirm signature validation and data mapping.
3. Verify that retries occur if you intentionally respond with 500.
4. Move to **Production** only after all scenarios pass.

***

## 9  Change Log

| Version | Date       | Notes                |
| ------- | ---------- | -------------------- |
| 1.0     | 2025-06-17 | Initial publication. |