LLPay API

Programmatically create UPI payment requests and check their status. All requests are JSON over HTTPS.

Base URL

/api/public/v1

Relative to your LLPay deployment, e.g. https://yourdomain.com/api/public/v1.

Authentication

All requests must include your API key as a bearer token. Generate keys in API keys.

Authorization: Bearer llp_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

POST /payments

Create a new payment request.

Request body

{
  "amount": 499.00,
  "customer_name": "Aman Verma",
  "customer_email": "aman@example.com",
  "customer_phone": "+91 98765 43210",
  "external_ref": "order_12345"
}

Response (201)

{
  "id": "b13a...",
  "status": "pending",
  "amount": 499.00,
  "currency": "INR",
  "upi_id": "merchant@upi",
  "upi_intent": "upi://pay?pa=...",
  "pay_url": "https://yourdomain.com/pay/b13a...",
  "external_ref": "order_12345",
  "created_at": "2026-05-22T12:34:56Z",
  "expires_at": "2026-05-22T13:04:56Z"
}

GET /payments/:id

Look up the status of a payment.

curl https://yourdomain.com/api/public/v1/payments/<id> \
  -H 'Authorization: Bearer llp_live_...'

Response (200)

{
  "id": "b13a...",
  "status": "approved",
  "amount": 499.00,
  "utr_reference": "412345678901",
  "external_ref": "order_12345",
  "approved_at": "2026-05-22T12:38:11Z"
}

Status values: pending, approved, rejected, expired.

GET /me

Retrieve your merchant profile and current balance.

{
  "merchant_id": "...",
  "business_name": "My Shop",
  "balance": 14200.50,
  "currency": "INR"
}

Errors

  • 400 — invalid request body
  • 401 — missing or invalid API key
  • 403 — accessing a payment from a different merchant
  • 404 — payment or merchant not found
  • 503 — no active collection UPI accounts configured

Webhooks

Register endpoints in Webhooks to receive a signed HTTP POST whenever a payment changes status.

Events

  • payment.approved — payment was approved by admin
  • payment.rejected — payment was rejected by admin
  • payment.expired — payment expired before approval

Headers

x-llpay-event: payment.approved
x-llpay-timestamp: 1716499200
x-llpay-signature: t=1716499200,v1=<hex hmac sha256>
x-llpay-delivery-id: <uuid>

Body

{
  "event": "payment.approved",
  "created_at": "2026-05-22T12:38:11Z",
  "data": {
    "id": "b13a...",
    "merchant_id": "...",
    "amount_cents": 49900,
    "currency": "INR",
    "status": "approved",
    "utr_reference": "412345678901",
    "external_ref": "order_12345",
    "customer_name": "Aman Verma",
    "customer_email": "aman@example.com",
    "approved_at": "2026-05-22T12:38:11Z"
  }
}

Verifying the signature (Node.js)

import crypto from 'crypto';

function verify(req, secret) {
  const header = req.headers['x-llpay-signature']; // "t=...,v1=..."
  const parts = Object.fromEntries(header.split(',').map(p => p.split('=')));
  const expected = crypto.createHmac('sha256', secret)
    .update(parts.t + '.' + req.rawBody)
    .digest('hex');
  return crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected));
}

Retries: failed deliveries (non-2xx or timeout) retry up to 6 times with backoff (30s → 1m → 5m → 30m → 2h → 6h). Respond 2xx within 10 seconds.