← Home

Documentation

Getting started with the panel, plus the full REST API reference.

Getting started

01

Register or sign in

Create an account with email + password. An API key is generated for you automatically.

02

Connect a merchant

Add your Paytm Business, FamPay, BharatPe or custom UPI account once. Credentials are stored securely and only used server-side.

03

Create an order

From the panel or the API. You get an order ID and a public pay link like /pay/<token> — share it and the payer sees a UPI QR plus app intent buttons.

04

Verify status

The pay page auto-polls every 2 seconds for 10 minutes. Successful payments settle instantly; unpaid links expire cleanly. One transaction record per order.

Authentication

Every request is authenticated with your API key, sent in the x-api-key header. You can also send it as Authorization: Bearer <key> or as a user_token body field.

Create and rotate keys on the API keys page. Every key carries a scope that decides which merchant accounts it can charge: All merchants (rotates across everything), Provider (rotates inside one provider) or Account (one fixed account). Each key also carries the payment page template its links use. Because routing and template live on the key, order requests only send the amount and customer details. Keep keys server-side — they can create orders on your account.

Base URL
https://mxpay.vip

Fallback Base URL (if your host can't reach the custom domain)
https://paytmbs.lovable.app

Header
x-api-key: <your_api_key>
Content-Type: application/json

Both hosts serve the same API. If your server's outbound connection to mxpay.vip times out (common on shared hosting behind restrictive firewalls), retry the same request against paytmbs.lovable.app. The PHP kit does this automatically.

Merchant routing

You can connect many accounts — ten Paytm Business accounts, a couple of FamPay accounts, and so on. When an order is created, BlackPay picks exactly one of them to collect the money. You control that choice when you create the API key — the request body never carries routing fields.

1. All connected merchants (rotate)

Create a key with scope All merchants — every active account, across every provider, is eligible. One is picked by weighted random: an account with weight 3 receives roughly three times the traffic of a weight 1 account. Weights are set per account on the Merchants page.

curl -X POST https://mxpay.vip/api/public/v1/order/create \
  -H "x-api-key: $ALL_MERCHANTS_KEY" -H "Content-Type: application/json" \
  -d '{ "amount": 149.5 }'

2. One provider (rotate inside it)

Create a Provider-scoped key and pick the provider in the form. Rotation still happens, but only among that provider's active accounts — useful when you want all traffic on Paytm Business while still spreading it over ten UPI IDs.

curl -X POST https://mxpay.vip/api/public/v1/order/create \
  -H "x-api-key: $PAYTM_ONLY_KEY" -H "Content-Type: application/json" \
  -d '{ "amount": 149.5 }'

3. One specific account

Create an Account-scoped key and choose the connected account in the form. No rotation — that one account always collects.

curl -X POST https://mxpay.vip/api/public/v1/order/create \
  -H "x-api-key: $STORE_NORTH_KEY" -H "Content-Type: application/json" \
  -d '{ "amount": 149.5 }'

Rules worth knowing

  • The key decides the routing. provider, merchant_account_id, account_label and template are no longer read from the request body — if an older integration still sends them they are ignored, not rejected.
  • Paused accounts are skipped. If every matching account is paused, the API returns 409.
  • FamPay accounts only join the rotation once Gmail is connected for them.
  • The account that was chosen comes back on every create response as provider, merchant_account_id and account_label, and its “last used” time is stamped so you can audit the spread.

Create order

POST/api/public/v1/order/create

Creates a payment and returns a shareable UPI pay link valid for 10 minutes.

FieldTypeDescription
amountnumberRequired. Amount in INR, greater than 0.
customer_mobilestringOptional. 10-digit customer mobile.
redirect_urlstringOptional. Browser redirect after success (order_id & status appended).
callback_urlstringOptional. Server-to-server webhook POSTed when the order finishes.
remark1stringOptional. Your internal reference, shown on the pay page.
remark2stringOptional. Second free-form note.
curl -X POST https://mxpay.vip/api/public/v1/order/create \
  -H "x-api-key: $PAYHUB_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 149.5,
    "customer_mobile": "9876543210",
    "remark1": "invoice-1042"
  }'
{
  "status": true,
  "data": {
    "order_id": "BYTE47121785237322231",
    "provider": "PAYTM",
    "merchant_account_id": "6f1c9d2e-6f4a-4b3c-9f01-2d0a7c5b8e11",
    "account_label": "store-north",
    "amount": 149.5,
    "template": "template_4",
    "payment_url": "https://mxpay.vip/pay/9xKq...",
    "link_token": "9xKq...",
    "expires_at": "2026-07-29T10:35:00.000Z"
  }
}

Payment page templates. Every link renders one of ten mobile-first designs. You pick the design when you create the API key: random picks a random enabled design, all rotates through your enabled designs in order, and template_1template_10 pin a specific one. Without a choice on the key, the default mode from your Payment page settings applies. The resolved design is returned as template and stays fixed for that link.

Order status

POST/api/public/v1/order/status
GET/api/public/v1/order/status?order_id=...

Returns the current state of an order. Poll every 3–5 seconds while the payer is on the pay page; the order settles to a terminal state within 10 minutes.

curl -X POST https://mxpay.vip/api/public/v1/order/status \
  -H "x-api-key: $PAYHUB_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "order_id": "BYTE47121785237322231" }'
{
  "status": true,
  "data": {
    "order_id": "BYTE47121785237322231",
    "provider": "PAYTM",
    "amount": 149.5,
    "txn_status": "TXN_SUCCESS",
    "utr": "419812345678",
    "gateway_txn": "20260729111212800110168...",
    "paid_at": "2026-07-29T10:32:11.000Z",
    "expires_at": "2026-07-29T10:35:00.000Z",
    "payment_url": "https://mxpay.vip/pay/9xKq..."
  }
}

Status values

  • PENDING — awaiting payment; keep polling.
  • TXN_SUCCESS — money received and amount matched. Terminal.
  • FAILED — the 5-minute window closed without a verified credit. Terminal.
  • EXPIRED — link no longer usable. Terminal.

PHP integration kit

Ready-made PHP files to plug this gateway into any PHP website — a cURL client, a checkout form, a return page and a JSON polling endpoint.

Download php-kit.zip

  • config.php — base URL, API key, return URL
  • BlackPay.php — client with createOrder / orderStatus / isPaid
  • checkout.php — amount form that redirects to the payment page
  • popup-checkout.php + create-order-ajax.php — self-checkout popup example
  • return.php — verifies the final status server-side
  • status-api.php — JSON endpoint for AJAX polling
require 'config.php';
require 'BlackPay.php';

$bp = new BlackPay(BLACKPAY_BASE_URL, BLACKPAY_API_KEY);
$order = $bp->createOrder(149.50, '9999999999', BLACKPAY_RETURN_URL);
header('Location: ' . $order['payment_url']);

// later, after the payer returns:
if ($bp->isPaid($order['order_id'])) { /* deliver the goods */ }

Only mark an order paid when the server-side status is TXN_SUCCESS. Never put the API key in browser JavaScript.

Freecharge auto-verification

A Freecharge merchant account can confirm payments automatically by signing in with the account's mobile number and an OTP. Open Merchants → Freecharge → Edit, save the account, then enter the mobile number and the OTP you receive.

How the login works

  • 1. A CSRF token is created for the anonymous session.
  • 2. Per-session encryption keys are generated.
  • 3. The OTP is sent to your Freecharge mobile number.
  • 4. Verifying the OTP returns the session cookie, which is encrypted before storage.

How a payment is matched

While an order is pending, recent Freecharge transactions are read and a credit is accepted when its Comments field contains the order reference, or when the amount matches exactly inside the order window. On a match the order becomes TXN_SUCCESS with the UPI reference stored as the UTR.

Session expiry

Freecharge sessions cannot be refreshed silently. When a session stops working the account is marked expired, admins are alerted, and verification pauses until you log in again with a new OTP. Orders keep working meanwhile and can still be verified manually.

OTPs, cookies and CSRF tokens are never logged; session cookies are stored encrypted and are never returned to the browser.

Errors

Errors return a non-2xx code with { "status": false, "error": "..." }.

  • 401 — missing, invalid or expired API key.
  • 404 — order not found on your account.
  • 409 — that merchant is not connected, or FamPay needs Gmail linked.
  • 422 — invalid request body.