UPI QR API
One endpoint that turns a UPI ID into a styled, scannable payment QR code — with themes, shapes, a preset amount/note and an embedded logo. Returns a PNG/SVG image, or JSON with a base64 data URI.
Authentication
Create a free account
to get an API key instantly. Send it on every request as the X-Api-Key header
(an api_key query parameter also works).
X-Api-Key: uqa_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Endpoint
POST
/api/v1/qr
Accepts multipart/form-data (for logo uploads) or standard form/JSON fields.
Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| upi_id | string | Required | The UPI VPA to pay, e.g. name@bank. |
| payee_name | string | Optional | Name shown to the payer in their UPI app. |
| amount | number | Optional | Preset amount. Omit to let the payer enter any amount. |
| note | string | Optional | Transaction note / description (max 100 chars). |
| theme | string | Optional | One of the named colour themes below. Default: classic. |
| shape | string | Optional | "square" or "soft" module rendering. Default: square. |
| format | string | Optional | "png" or "svg". Default: png. |
| size | integer | Optional | Output size in pixels, 200–2000. Default: 512. |
| margin | integer | Optional | Quiet-zone margin in pixels, 0–100. Default: 16. |
| output | string | Optional | "image" (binary, default) or "json" (base64 data URI). |
| logo | file | Optional | PNG/JPG/WEBP file, max 2MB, embedded & punched out in the centre. |
| logo_url | string | Optional | HTTPS image URL to use as the logo instead of a file upload. |
Response formats
By default the API streams back the image directly with the correct Content-Type. Pass output=json to get a data URI instead — handy for previewing in a browser without a temp file.
{
"ok": true,
"mime_type": "image/png",
"data_uri": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."
}
Code examples
curl -X POST https://upiapi.atdb.uno/api/v1/qr \
-H "X-Api-Key: YOUR_API_KEY" \
-F "upi_id=yourname@upi" \
-F "payee_name=Coffee Shop" \
-F "amount=499" \
-F "note=Order #128" \
-F "theme=ocean" \
-F "shape=soft" \
-F "logo=@logo.png" \
-o qr.png
const form = new FormData();
form.append('upi_id', 'yourname@upi');
form.append('payee_name', 'Coffee Shop');
form.append('amount', '499');
form.append('theme', 'ocean');
form.append('shape', 'soft');
form.append('output', 'json');
const res = await fetch('https://upiapi.atdb.uno/api/v1/qr', {
method: 'POST',
headers: {'X-Api-Key': 'YOUR_API_KEY'},
body: form,
});
const { data_uri } = await res.json();
document.querySelector('#qr').src = data_uri;
<?php
$ch = curl_init('https://upiapi.atdb.uno/api/v1/qr');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-Api-Key: YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'upi_id' => 'yourname@upi',
'payee_name' => 'Coffee Shop',
'amount' => '499',
'theme' => 'ocean',
'shape' => 'soft',
'logo' => new CURLFile('logo.png'),
],
]);
$png = curl_exec($ch);
curl_close($ch);
file_put_contents('qr.png', $png);
import requests
response = requests.post(
"https://upiapi.atdb.uno/api/v1/qr",
headers={"X-Api-Key": "YOUR_API_KEY"},
data={
"upi_id": "yourname@upi",
"payee_name": "Coffee Shop",
"amount": "499",
"theme": "ocean",
"shape": "soft",
},
files={"logo": open("logo.png", "rb")},
)
with open("qr.png", "wb") as f:
f.write(response.content)
Themes & shapes
Pass any of these as theme. See them live on the components page.
Errors & rate limits
| Status | Error | Meaning |
|---|---|---|
| 401 | missing_api_key / invalid_api_key | No key sent, or the key was not recognised. |
| 402 | payment_required | The API is in paid mode and your account has not activated paid access yet. |
| 422 | validation_failed | One or more parameters were invalid — see the errors object. |
| 429 | too_many_requests | You have exceeded 60 requests/minute. |
| 500 | generation_failed | Something went wrong while rendering the QR code. |
Requests are limited to 60/minute per API key.