One plan. One payment. ₹7,800 for lifetime · 0% commission on every transaction Toll-free 1800 909 111

UPIstar API Reference

Everything you need to create UPI orders, receive real-time payment webhooks and confirm payments in your own application.

Introduction

The UPIstar API is a JSON REST API served over HTTPS. Every request and response body is JSON, every amount is in Indian Rupees (INR), and every timestamp is ISO 8601.

Base URL  https://api.upistar.in/v1

A typical integration has three steps:

  1. Create an order from your server when the customer clicks Pay.
  2. Redirect the customer to the returned payment_url, or render the upi_intent yourself.
  3. Receive a webhook when payment succeeds and mark the order as paid in your database.

Authentication

Authenticate each request with your secret API key, sent as a Bearer token. Find your keys in Dashboard → Settings → API Keys.

Authorization: Bearer usk_live_xxxxxxxxxxxxxxxxxxxxxxxx
Keep your secret key on your server. Never put it in mobile apps, browser JavaScript or public repositories. If a key leaks, rotate it from the dashboard immediately.

Sandbox & live mode

Each account has two key pairs. Keys starting with usk_test_ create sandbox orders that never move real money. Use the Simulate payment button in the dashboard to trigger a test webhook. Switch to usk_live_ keys when you are ready to go live.

Create order

POST /orders

Creates a payment request and returns a hosted checkout URL with a dynamic QR code.

Body parameters

FieldTypeDescription
order_idstringRequired. Your unique order reference (max 40 chars). Re-sending the same ID returns the existing order.
amountnumberRequired. Amount in INR, from 1 to 100000, up to 2 decimals.
customer_namestringCustomer's name, shown on the checkout page.
customer_emailstringOptional email for the payment receipt.
customer_mobilestringOptional 10-digit mobile number.
redirect_urlstringWhere to send the customer after payment.
notestringShort description shown in the customer's UPI app.
metaobjectUp to 10 key/value pairs returned to you in webhooks.

Example request

curl -X POST https://api.upistar.in/v1/orders \
  -H "Authorization: Bearer $UPISTAR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "order_id": "INV-1042",
    "amount": 1499,
    "customer_name": "Priya Rao",
    "redirect_url": "https://yourshop.in/thanks"
  }'
const res = await fetch('https://api.upistar.in/v1/orders', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.UPISTAR_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ order_id: 'INV-1042', amount: 1499 }),
});
const { data } = await res.json();
$ch = curl_init('https://api.upistar.in/v1/orders');
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('UPISTAR_KEY'), 'Content-Type: application/json'],
  CURLOPT_POSTFIELDS => json_encode(['order_id' => 'INV-1042', 'amount' => 1499]),
]);
$order = json_decode(curl_exec($ch), true);
import os, requests

r = requests.post(
    "https://api.upistar.in/v1/orders",
    headers={"Authorization": f"Bearer {os.environ['UPISTAR_KEY']}"},
    json={"order_id": "INV-1042", "amount": 1499},
    timeout=15,
)
order = r.json()["data"]
body := strings.NewReader(`{"order_id":"INV-1042","amount":1499}`)
req, _ := http.NewRequest("POST", "https://api.upistar.in/v1/orders", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("UPISTAR_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
HttpRequest req = HttpRequest.newBuilder()
    .uri(URI.create("https://api.upistar.in/v1/orders"))
    .header("Authorization", "Bearer " + System.getenv("UPISTAR_KEY"))
    .header("Content-Type", "application/json")
    .POST(BodyPublishers.ofString("{\"order_id\":\"INV-1042\",\"amount\":1499}"))
    .build();
HttpResponse<String> res = HttpClient.newHttpClient().send(req, BodyHandlers.ofString());

Response 201 Created

{
  "status": true,
  "message": "Order created",
  "data": {
    "order_id": "INV-1042",
    "amount": "1499.00",
    "currency": "INR",
    "status": "pending",
    "payment_url": "https://pay.upistar.in/ord_8f2k1m9x4q",
    "upi_intent": "upi://pay?pa=…&am=1499.00&tn=INV-1042",
    "expires_at": "2026-11-06T10:47:18+05:30"
  }
}
Orders expire after 5 minutes by default. Create a new order if the customer returns after expiry.

Check order status

GET /orders/{order_id}

Returns the latest state of an order. Use it as a fallback when a webhook is delayed, or to confirm a payment before you ship.

{
  "status": true,
  "data": {
    "order_id": "INV-1042",
    "amount": "1499.00",
    "status": "success",
    "utr": "402188761290",
    "payer_vpa": "priya@okbank",
    "paid_at": "2026-11-06T10:42:18+05:30"
  }
}

Verify by UTR

POST /orders/{order_id}/verify

If a customer paid but the order still shows pending (for example, they paid manually instead of through the QR), submit the 12-digit UTR from their UPI app. UPIstar checks it against the received credit and confirms the order if the amount matches.

{ "utr": "402188761290" }

Webhooks

Set your webhook URL in Dashboard → Settings → Webhooks. UPIstar sends a POST request with a JSON body whenever an order changes state.

EventWhen it fires
payment.successPayment was received and verified.
payment.failedThe customer's UPI app reported a failure.
order.expiredThe order expired without payment.

Payload

{
  "event": "payment.success",
  "order_id": "INV-1042",
  "amount": "1499.00",
  "currency": "INR",
  "status": "success",
  "utr": "402188761290",
  "payer_vpa": "priya@okbank",
  "meta": { "cart_id": "c_7781" },
  "paid_at": "2026-11-06T10:42:18+05:30"
}

Retries

Respond with any 2xx status within 10 seconds. Otherwise UPIstar retries up to 6 times over 24 hours (after 1 min, 5 min, 30 min, 2 h, 6 h and 24 h). Every attempt is visible in the webhook log, where you can also replay it manually.

Webhooks can occasionally arrive more than once. Make your handler idempotent: if the order is already marked paid, just return 200.

Verify signature

Each webhook includes an X-UPIstar-Signature header: an HMAC-SHA256 of the raw request body, signed with your webhook secret. Always verify it before trusting the payload.

import crypto from 'node:crypto';

function isValid(rawBody, header, secret) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');
  return header?.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(header), Buffer.from(expected));
}
$raw      = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $raw, getenv('UPISTAR_WEBHOOK_SECRET'));
$given    = $_SERVER['HTTP_X_UPISTAR_SIGNATURE'] ?? '';

if (!hash_equals($expected, $given)) {
  http_response_code(401);
  exit;
}
import hmac, hashlib

def is_valid(raw_body: bytes, header: str, secret: str) -> bool:
    expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, header or "")

Order statuses

StatusMeaning
pendingOrder created, waiting for the customer to pay.
successPayment received and verified. Safe to fulfil.
failedPayment attempt failed or was declined.
expiredNo payment received before the order expired.

Errors

Errors return "status": false with a human-readable message and a machine-readable code.

HTTPCodeMeaning
400invalid_requestA required field is missing or malformed.
401unauthorizedAPI key is missing, invalid or revoked.
404not_foundNo order exists with that ID.
409duplicate_orderThe order ID exists with a different amount.
422utr_mismatchThe UTR doesn't match a credit for this order.
429rate_limitedToo many requests. Retry after the Retry-After header.
500server_errorSomething went wrong on our side. Safe to retry.

Plugins & SDKs

🛒

WooCommerce / WordPress

Download the plugin from your dashboard, upload it under Plugins → Add New, paste your API key and enable UPIstar as a payment method. Orders auto-complete when paid.

{ }

Sample code

Ready-to-run examples for PHP, Node.js, Python, Go and Java are available in your dashboard under Developers → Samples.

Need help integrating? Email support@upistar.in or call 1800 909 111.