Dynamic UPI QR Generator
NO TOKEN REQUIREDGenerate an amount-specific UPI payment QR with a single URL. Pass a UPI ID and amount, and get back a ready-to-display PNG. Fully public — no account, no token, no SDK.
The entire integration
This is not a simplified example — this is the whole thing. One <img> tag, nothing else.
<img
src="https://webarchitect.in/products/apiV1/upi/qr?vpa=merchant@upi&amount=499"
alt="Scan to pay ₹499"
/>
No npm install. No <script>. No QR library. No Base64. No SDK. No backend integration. No UPI URI knowledge. Just an image URL.
Endpoint
GET /apiV1/upi/qr?vpa=merchant@upi&amount=499
| Param | Required | Description |
|---|---|---|
| vpa | Yes | UPI ID of the recipient, e.g. merchant@upi. Accepts both @ and its URL-encoded form %40. |
| amount | Yes | Payment amount in INR. Greater than zero, at most 2 decimal places. |
No merchant name parameter in v1 — the receiving UPI app determines payee display as supported by the UPI ecosystem.
Response
On success, the raw PNG bytes — directly displayable, nothing to decode:
HTTP/1.1 200 OK
Content-Type: image/png
On a validation error, the platform's standard JSON error shape instead (see Errors below) — your <img> will show a broken-image icon in that case, so validate vpa/amount before rendering the tag if they come from user input.
Errors
| Status | Code | Meaning |
|---|---|---|
| 400 | VPA_REQUIRED | vpa is missing. |
| 400 | INVALID_VPA | vpa doesn't look like a valid UPI ID. |
| 400 | AMOUNT_REQUIRED | amount is missing. |
| 400 | INVALID_AMOUNT | Not greater than zero, or more than 2 decimal places. |
| 429 | RATE_LIMITED | Too many requests from this IP — slow down. |
{
"success": false,
"error": {
"code": "INVALID_VPA",
"message": "Invalid UPI ID."
},
"meta": {
"request_id": "req_8f72c1a9..."
}
}
Need help?
Email [email protected] — include your request ID from the response meta.request_id if you have one.
curl "https://webarchitect.in/products/apiV1/upi/qr?vpa=merchant@upi&amount=499" --output qr.png
const res = await fetch("https://webarchitect.in/products/apiV1/upi/qr?vpa=merchant@upi&amount=499");
const buffer = Buffer.from(await res.arrayBuffer());
await fs.promises.writeFile("qr.png", buffer);
import requests
response = requests.get(
"https://webarchitect.in/products/apiV1/upi/qr",
params={"vpa": "merchant@upi", "amount": "499"},
)
with open("qr.png", "wb") as f:
f.write(response.content)
<?php
$png = file_get_contents(
"https://webarchitect.in/products/apiV1/upi/qr?vpa=merchant@upi&amount=499"
);
file_put_contents("qr.png", $png);
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://webarchitect.in/products/apiV1/upi/qr?vpa=merchant@upi&amount=499"))
.GET()
.build();
HttpResponse<byte[]> response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
Files.write(Path.of("qr.png"), response.body());
resp, err := http.Get("https://webarchitect.in/products/apiV1/upi/qr?vpa=merchant@upi&amount=499")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
out, _ := os.Create("qr.png")
defer out.Close()
io.Copy(out, resp.Body)
Only needed if you want to download/cache the PNG server-side (e.g. for a PDF invoice). For a web page, the <img> tag above is the whole integration.