Skip to content
LIVE PAYINS — real customer money via enabled live providers. Withdrawals remain simulated.
P PayGrid API

API documentation

REST API v1 · JSON over HTTPS

Every response carries "sandbox": true for simulated payments, false when a live provider processed real money.

Authentication

Send your credentials on every request over HTTPS. Generate them under API Keys & Webhooks. Limit: 60 requests/minute per key.

X-Api-Key: pk_sandbox_...
X-Api-Secret: sk_sandbox_...
Content-Type: application/json

POST /payin/create

Creates a pending payment and returns a checkout_url to send your customer to. Send an optional Idempotency-Key header (8–64 chars) to safely retry: the same key returns the original transaction.

curl -X POST https://jupiterpay.business/api/v1/payin/create \
  -H "X-Api-Key: $API_KEY" -H "X-Api-Secret: $API_SECRET" \
  -H "Idempotency-Key: order-1001-attempt-1" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "1000.00",
    "currency": "INR",
    "order_id": "order-1001",
    "customer": { "name": "Asha Rao", "email": "asha@example.com", "phone": "+919800000000" },
    "callback_url": "https://merchant.example/webhooks/paygrid",
    "return_url": "https://merchant.example/orders/1001"
  }'
FieldTypeNotes
amountstringDecimal, max 2 places, 1.00 – 1000000.00
currencystringINR
order_idstringYour reference; unique per merchant (≤64, [A-Za-z0-9_.-:])
customerobjectname, email required; phone optional
callback_urlstring?Server-to-server status notifications (overrides account webhook URL)
return_urlstring?Where the customer can go after seeing the result

Response 201:

{
  "sandbox": true,
  "transaction_id": "txn_4f1c...",
  "order_id": "order-1001",
  "status": "PENDING",
  "amount": "1000.00",
  "currency": "INR",
  "fee": "50.00",
  "net_amount": "950.00",
  "checkout_url": "https://jupiterpay.business/pay/txn_4f1c...",
  "failure_reason": null,
  "created_at": "2026-11-14T10:00:00.000Z",
  "completed_at": null
}

GET /payin/:transaction_id

Returns the same object. Use it to confirm status server-side before fulfilling an order.

Payment flow

  1. You call /payin/create → transaction is PENDING.
  2. Customer opens checkout_url → redirected to the provider's hosted checkout.
  3. Provider sends us a signed webhook. We verify the signature, de-duplicate it, then query the provider directly for the real status and amount.
  4. Only then: SUCCEEDED (net amount credited to your pending balance) or FAILED. Unpaid payments become EXPIRED after 30 minutes.
  5. We POST a signed notification to your callback/webhook URL. Settlement later moves funds from pending to available.

Customer browser redirects are never treated as proof of payment — by us or, please, by you.

Webhooks to your server

POST <your callback_url>
X-Gateway-Event-Id: evt_...
X-Gateway-Timestamp: 1763114400
X-Gateway-Signature: hex(HMAC_SHA256(webhook_signing_secret, timestamp + "." + raw_body))

{ "id": "evt_...", "type": "payin.succeeded", "sandbox": true, "data": { ...transaction } }

Verify (Node.js):

import crypto from "node:crypto";

function verify(rawBody, headers, secret) {
  const ts = headers["x-gateway-timestamp"];
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false; // replay window
  const expected = crypto.createHmac("sha256", secret).update(`${ts}.${rawBody}`).digest("hex");
  const given = Buffer.from(headers["x-gateway-signature"] ?? "");
  return given.length === expected.length && crypto.timingSafeEqual(given, Buffer.from(expected));
}

Event types: payin.succeeded, payin.failed, payin.expired. Treat id as an idempotency key on your side.

Fees

Payin commission (default 5%) is deducted from each successful payin: ₹1,000 → fee ₹50 → ₹950 credited. Payout commission (default 3%) is deducted from each withdrawal: ₹1,000 → fee ₹30 → ₹970 paid out. Rates are snapshotted on each transaction.

Errors

{ "error": { "code": "validation_error", "message": "Invalid request", "details": { ... } } }
400invalid_json
401unauthorized
403merchant_suspended
404not_found
409duplicate_order
422validation_error · invalid_amount · unsupported_currency · idempotency_mismatch
429rate_limited
502provider_error
503provider_unavailable