RupayDeveloper docsOpenAPI specification

Migrating from Stripe Checkout

Rupay uses a Checkout Session-style server API but hosts a page that can offer card and local payment rails. The main migration is replacing session creation, redirect URL ownership, and webhook verification.

Mapping

Stripe CheckoutRupay Hosted Checkout
stripe.checkout.sessions.create(...)POST /v1/checkout/sessions
Stripe secret keyRupay rp_test_ or rp_live_ API key
Stripe Price IDsRupay Price IDs in line_items[].price
Stripe-hosted session URLRupay-hosted url
checkout.session.completed from Stripecheckout.session.completed signed by Rupay
Stripe session retrievalAuthenticated Rupay session retrieval
Stripe webhook secretRupay merchant signing secret

Rupay does not expose its internal provider invoice IDs. Integrations should use Rupay session IDs and their own client_reference_id.

Before

const session = await stripe.checkout.sessions.create({
  mode: "payment",
  line_items: [{ price: "price_123", quantity: 1 }],
  success_url: `${origin}/success?session_id={CHECKOUT_SESSION_ID}`,
  cancel_url: `${origin}/cancel`,
});

After

const response = await fetch(
  `${process.env.RUPAY_API_BASE_URL}/v1/checkout/sessions`,
  {
    method: "POST",
    headers: {
      authorization: `Bearer ${process.env.RUPAY_API_KEY}`,
      "content-type": "application/json",
      "idempotency-key": `order-${order.id}`,
    },
    body: JSON.stringify({
      mode: "payment",
      client_reference_id: order.id,
      currency: "npr",
      line_items: [
        {
          description: "Order total",
          quantity: 1,
          amount_unit: order.totalMinor,
        },
      ],
      success_url: `${origin}/success?session_id={CHECKOUT_SESSION_ID}`,
      cancel_url: `${origin}/cancel`,
      metadata: { order_id: order.id },
    }),
  },
);

if (!response.ok) throw new Error("Rupay session creation failed");
const session = await response.json();
redirect(session.url);

Stripe SDK integration

For the supported fixed-period purchase flow, pin Stripe Node 20.4.1 and apiVersion: "2026-02-25.clover", set its host/protocol/port to Rupay, and use a Rupay API key. customers.create/retrieve, products.list/retrieve, prices.list/retrieve, checkout.sessions.create/retrieve/expire, and webhookEndpoints.create are supported as described in the compatibility contract.

line_items: [{ price: "price_...", quantity: 1 }] now accepts Rupay's immutable catalog Price IDs. Native product/variant checkout requests and inline price_data continue to work. For fixed-term access, use mode: "payment"; mode: "subscription" is rejected because recurring collection is not implemented.

The SDK sends the pinned Stripe-Version header to select compatible response shapes. Native requests without it retain Rupay's existing response format. SDK-created webhook endpoints receive SDK-shaped checkout.session.completed events with a Stripe-Signature header and a separate endpoint secret. Use constructEventAsync in Cloudflare/Bun. Existing native endpoints are unchanged.

See the Nepse Edge SDK example for customer mapping, Price configuration, checkout creation, signature verification, and fulfillment. This is a supported subset, not a claim of complete Stripe API compatibility.