Auto Upi API documentation

Auto Upi is a self-serve UPI collection gateway. Create an order from your server and open the hosted checkout as a popup on your own website. Orders are confirmed automatically — no commission, money straight into your UPI account.

BASE URLhttps://autoupi.in/api/public/v1
FORMATapplication/json
AUTH HEADERX-API-Key

Quickstart

  1. Create an account and sign in to the merchant console.
  2. Connect an account — pick PhonePe or Paytm and complete the setup on the Connect Accounts page.
  3. Generate an API key on the API Keys page. Copy it once; regenerating replaces the old key.
  4. Copy the webhook secret from API Keys and store both credentials securely on your server.
  5. Set your webhook URL on Config, or pass your HTTPS webhook endpoint when creating each order.
  6. Load the popup script once from https://autoupi.in/checkout.js.
  7. Create an order from your server, save its ID against the buyer, then call AutoUpi.open({ url: payment_url }) on your page. See Popup checkout.
  8. Confirm payment through your signed webhook or a server-side status check, then update the same page and fulfil the order once.

Authentication

Every request carries your secret key in the X-API-Key header. Keys start withaupi_live_ and are stored hashed — an old key can never be shown again. Call the API only from your server; never expose the key in browser code.

header
X-API-Key: aupi_live_xxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json

Create order

POST /api/public/v1/create-order

FieldTypeRequiredDescription
amountnumberYesOrder amount in INR, 1 to 10,00,000.
customer_namestringNoShown on the checkout page.
webhook_urlstringNoHTTPS URL that receives the signed payment.paid webhook.
link_typestringNoone_time (default) or reusable.
curl
curl -X POST https://autoupi.in/api/public/v1/create-order \
  -H "X-API-Key: aupi_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{"amount": 1499, "customer_name": "Rahul Sharma", "webhook_url": "https://yoursite.com/autoupi-webhook.php"}'
200 response
{
  "ok": true,
  "order_id": "ORD20260915A1B2C3",
  "slug": "9fkq2wra",
  "amount": 1499,
  "payable_amount": 1499.37,
  "status": "active",
  "payment_url": "https://autoupi.in/pay/9fkq2wra"
}

Always charge payable_amount: it can differ from amount by up to ₹0.99 so each active order stays unique. The customer pays payable_amount; your books are credited with the base amount.

Order status

GET /api/public/v1/order-status?order_id=ORD…

Check this endpoint from your server during checkout or after a popup callback to confirm payment before fulfilment. Your page calls your own status endpoint; it never sends the API key to Auto Upi directly.

curl
curl "https://autoupi.in/api/public/v1/order-status?order_id=ORD20260915A1B2C3" \
  -H "X-API-Key: aupi_live_your_key"
200 response
{
  "ok": true,
  "order": {
    "order_id": "ORD20260915A1B2C3",
    "slug": "9fkq2wra",
    "customer_name": "Rahul Sharma",
    "amount": 1499,
    "payable_amount": 1499.37,
    "status": "paid",
    "payer_name": "RAHUL SHARMA",
    "paid_at": "2026-09-15T10:21:44.120Z",
    "detected_at": "2026-09-15T10:21:52.480Z",
    "expires_at": "2026-09-15T10:26:00.000Z"
  }
}
StatusMeaning
activeWaiting for payment. Links expire 5 minutes after creation.
paidA matching credit alert was detected. Safe to fulfil.
expiredNo payment detected in time. Create a new order.

Webhooks

Each API key ships with a webhook secret (whsec_…) shown on the API Keys page. Pass awebhook_url when creating an order and we POST a signed payment.paid event the moment the order is confirmed as paid. You can also save one default webhook URL on the Config page in your dashboard — it is used for every order of your account when the create order call does not send its own webhook_url.

payload
POST https://yoursite.com/autoupi-webhook.php
X-AutoUpi-Signature: t=1789453200,v1=6f3c…9ab

{
  "event": "payment.paid",
  "order_id": "ORD20260915A1B2C3",
  "amount": 1499,
  "payable_amount": 1499.37,
  "status": "paid",
  "payer_name": "RAHUL SHARMA",
  "paid_at": "2026-09-15T10:21:44.120Z"
}

signed_payload = "{t}." + raw_request_body
v1 = hex(hmac_sha256(webhook_secret, signed_payload))
php
<?php
// autoupi-webhook.php
$secret = getenv("AUTOUPI_WEBHOOK_SECRET");
$raw    = file_get_contents("php://input");
$header = $_SERVER["HTTP_X_AUTOUPI_SIGNATURE"] ?? "";

parse_str(str_replace(",", "&", $header), $parts);   // t=..., v1=...
$expected = hash_hmac("sha256", $parts["t"] . "." . $raw, $secret);

if (!hash_equals($expected, $parts["v1"] ?? "")) {
  http_response_code(401);
  exit("bad signature");
}

$event = json_decode($raw, true);
if ($event["event"] === "payment.paid") {
  // idempotent: skip if this order_id is already fulfilled
  mark_order_paid($event["order_id"], $event["amount"]);
}
http_response_code(200);
echo "ok";

Always treat delivery as at-least-once and keep your handler idempotent.

PHP integration in 3 files

Use these three server-side files with the HTML / JavaScript popup example above. Store the API key and webhook secret securely, and connect the order-saving and fulfilment hooks to your existing site. WordPress, Laravel and CodeIgniter should use their own session, CSRF and request handling conventions.

1. autoupi.php — tiny helper class
<?php
class AutoUpi {
  private string $key;
  private string $base;

  public function __construct(string $key, string $base = "https://autoupi.in/api/public/v1") {
    $this->key = $key;
    $this->base = $base;
  }

  private function request(string $url, ?array $body = null): array {
    $ch = curl_init($url);
    $headers = ["X-API-Key: {$this->key}"];
    if ($body !== null) {
      $headers[] = "Content-Type: application/json";
      curl_setopt($ch, CURLOPT_POST, true);
      curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
    }
    curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => $headers, CURLOPT_TIMEOUT => 20]);
    $res = json_decode(curl_exec($ch), true);
    curl_close($ch);
    return is_array($res) ? $res : ["ok" => false, "error" => "network_error"];
  }

  public function createOrder(float $amount, string $customer = "", string $webhook = ""): array {
    return $this->request($this->base . "/create-order", [
      "amount" => $amount,
      "customer_name" => $customer,
      "webhook_url" => $webhook,
    ]);
  }

  public function status(string $orderId): array {
    return $this->request($this->base . "/order-status?order_id=" . urlencode($orderId));
  }

  public static function verify(string $raw, string $header, string $secret): bool {
    parse_str(str_replace(",", "&", $header), $p);
    if (empty($p["t"]) || empty($p["v1"])) return false;
    return hash_equals(hash_hmac("sha256", $p["t"] . "." . $raw, $secret), $p["v1"]);
  }
}
2. checkout.php — return the popup order
<?php
require "autoupi.php";
// Require POST, authenticate the buyer, and validate CSRF using your app.
$api = new AutoUpi(getenv("AUTOUPI_KEY"));

$order = $api->createOrder(1499, "Rahul Sharma", "https://yoursite.com/autoupi-webhook.php");

if (empty($order["ok"])) {
  http_response_code(400);
  header("Content-Type: application/json");
  echo json_encode(["ok" => false, "error" => "Could not start payment"]);
  exit;
}

// store it so the webhook can find the buyer later
save_order($order["order_id"], $_SESSION["user_id"], $order["amount"]);

// save_order is your application's function, not an Auto Upi SDK method.
header("Content-Type: application/json");
echo json_encode(["ok" => true, "order_id" => $order["order_id"], "payment_url" => $order["payment_url"]]);
exit;
3. autoupi-webhook.php — get paid automatically
<?php
require "autoupi.php";

$raw = file_get_contents("php://input");
$sig = $_SERVER["HTTP_X_AUTOUPI_SIGNATURE"] ?? "";

if (!AutoUpi::verify($raw, $sig, getenv("AUTOUPI_WEBHOOK_SECRET"))) {
  http_response_code(401);
  exit("bad signature");
}

$event = json_decode($raw, true);
if (($event["event"] ?? "") === "payment.paid") {
  // amount = your original order value; payable_amount = what the customer actually paid
  // Look up the saved order and verify its amount before fulfilment.
  // Your mark_order_paid function must handle duplicate delivery atomically.
  mark_order_paid($event["order_id"], $event["amount"]);
}

http_response_code(200);
echo "ok";

No webhook endpoint yet? Your page can call your own server to check order-status while the popup is open and after a result. Authenticate the buyer, check order ownership and fulfil once only when the server confirms paid. Never put the API key in that page.

Errors

HTTPCodeFix
401invalid_api_keyKey missing, revoked or replaced by a regenerate.
400invalid_amountAmount must be greater than 0 and up to 10,00,000.
400UPI_NOT_CONFIGUREDSave a UPI ID on Connect Accounts first.
400QUOTA_EXCEEDEDQR limit finished — upgrade to Pro.
400ALL_PAYMENT_SLOTS_BUSYToo many pending orders at the same amount; retry shortly.
404not_foundThe order ID does not belong to this key.

Pricing

No per-transaction commission — you collect straight into your own UPI account.

Free

₹0to get started
  • 3 payment QR codes total
  • 1 merchant account
  • Full REST API access
  • Automatic payment confirmation
Create account

Custom

Talk to ushigh volume
  • Higher QR limits
  • Multiple merchant accounts
  • Self-hosted deployment
  • Dedicated support
Contact sales

FAQ

Do I need a payment gateway account?

No. Money reaches your own UPI account directly; Auto Upi only confirms and records the order.

What if two customers pay the same amount?

They can't — each active order carries its own unique payable_amount.

How long is a link valid?

5 minutes. After that the order becomes expired and moves to Transactions.

Which PHP version do I need?

PHP 7.4 or newer with the cURL extension — no composer package required.

Can I regenerate my API key?

Yes. Regenerating issues a new key and instantly disables the previous one.