PayBridgeNP

PayBridgeNP

Nepal payments

Back to Blog
developerpayment-gatewaynepaltutorial

Nepal Payment Gateway API: Integration Guide for Developers

A practical developer guide to integrating Nepal payment APIs - authentication, checkout sessions, webhooks, refunds, and the PayBridgeNP TypeScript SDK.

March 20, 20264 min readPayBridgeNP Team
Nepal Payment Gateway API: Integration Guide for Developers

If you're building a product for the Nepali market and need to accept payments, this guide covers everything you need as a developer. We'll cover the full integration lifecycle with working code examples.

Overview: What You're Building

A complete payment integration in Nepal typically involves:

  1. Creating a checkout session - your server creates a session with the amount and customer details
  2. Redirecting to checkout - the customer pays on a hosted page
  3. Receiving a webhook - your server is notified of the payment outcome
  4. Verifying and fulfilling - you verify the webhook signature and fulfill the order

This pattern is identical whether you're building with Node.js, Python, PHP, or any other backend.

Authentication

PayBridgeNP uses bearer token authentication. All API requests must include your secret key:

Authorization: Bearer sk_live_your_secret_key

Keep your secret key server-side only. Never expose it in client-side JavaScript, mobile apps, or public repositories.

Key types:

  • sk_live_... - live secret key (server-side only, real payments)
  • sk_test_... - sandbox secret key (server-side only, no real money moves)

Keep secret keys server-side only. PayBridgeNP has no client-safe publishable keys.

Installing the SDK

TypeScript / Node.js

npm install @paybridge-np/sdk
# or
bun add @paybridge-np/sdk

Python

pip install paybridge-np

PHP

composer require paybridge-np/sdk

Creating a Checkout Session

This is the core operation. Your server creates a session; the customer completes payment on PayBridgeNP's hosted checkout.

import { PayBridge } from "@paybridge-np/sdk";

const paybridge = new PayBridge({
  apiKey: process.env.PAYBRIDGE_API_KEY!,
});

// In your order handler:
const session = await paybridge.checkout.create({
  amount: 250000, // Amount in paisa (NPR 2,500.00)
  currency: "NPR",
  customer: {
    name: "Binod Karki",
    email: "binod@example.com",
    phone: "9851234567",
  },
  successUrl: "https://yoursite.com/orders/{CHECKOUT_SESSION_ID}/success",
  cancelUrl: "https://yoursite.com/checkout",
  metadata: {
    orderId: "ORD-12345",
    userId: "usr_abc",
  },
});

// Redirect the customer
return redirect(session.checkoutUrl);

Amount is in paisa (1 NPR = 100 paisa). This is the standard for payment APIs - it avoids floating-point issues with decimal amounts.

Handling the Webhook

When the customer completes (or fails) payment, PayBridgeNP sends a POST request to your registered webhook URL.

import { createHmac } from "crypto";
import type { Request, Response } from "express";

export async function handleWebhook(req: Request, res: Response) {
  const signature = req.headers["paybridge-signature"] as string;
  const body = req.rawBody; // needs raw body, not parsed JSON

  // Verify the signature
  const expected = createHmac("sha256", process.env.PAYBRIDGE_WEBHOOK_SECRET!)
    .update(body)
    .digest("hex");

  if (signature !== `sha256=${expected}`) {
    return res.status(401).json({ error: "Invalid signature" });
  }

  const event = JSON.parse(body);

  switch (event.type) {
    case "payment.succeeded": {
      const { metadata, amount, provider } = event.data;
      await fulfillOrder(metadata.orderId);
      console.log(`Order ${metadata.orderId} paid via ${provider}`);
      break;
    }
    case "payment.failed": {
      await markOrderFailed(event.data.metadata.orderId);
      break;
    }
    case "payment.cancelled": {
      await releaseInventory(event.data.metadata.orderId);
      break;
    }
  }

  return res.json({ received: true });
}

Always verify webhook signatures. Unverified webhooks are a security vulnerability - an attacker could POST fake "payment.succeeded" events to your endpoint.

Webhook Events Reference

EventWhen it fires
payment.succeededPayment successful
payment.failedPayment declined or error
payment.cancelledCustomer didn't pay within timeout
payment.refundedRefund fully processed
payment.refundedRefund failed

Idempotency

Always design your fulfillment logic to be idempotent. Webhooks can be delivered more than once. Check if you've already fulfilled the order before acting:

case "payment.succeeded": {
  const order = await db.orders.findOne({ id: event.data.metadata.orderId });
  if (order.status === "fulfilled") break; // already handled
  await fulfillOrder(order.id);
  break;
}

Retrieving a Payment

You can fetch payment details at any time:

const payment = await paybridge.payments.retrieve("pay_abc123");
console.log(payment.status); // "completed" | "failed" | "pending"
console.log(payment.provider); // "khalti" | "esewa" | "connectips"
console.log(payment.amount); // 250000 (paisa)

Processing Refunds

const refund = await paybridge.refunds.create({
  paymentId: "pay_abc123",
  amount: 250000, // Full refund. Partial: specify less than original
  reason: "Customer requested cancellation",
});

console.log(refund.status); // "pending" | "completed"

Refunds are processed back to the original payment method. Processing time:

  • Khalti: instant to 1 business day
  • eSewa: 1-3 business days
  • ConnectIPS: 2-5 business days

Sandbox Testing

Use sandbox keys (sk_test_...) for development. The sandbox behaves identically to production but no real money moves.

Sandbox test credentials are in your PayBridgeNP dashboard under Developers > Sandbox.

Error Handling

try {
  const session = await paybridge.checkout.create({ ... });
} catch (error) {
  if (error instanceof PayBridge.APIError) {
    console.error(error.status);  // HTTP status code
    console.error(error.code);    // "invalid_amount" | "provider_unavailable" | etc.
    console.error(error.message); // Human-readable message
  }
}

Next Steps


Related Articles

Ready to accept payments in Nepal?

Connect Khalti, eSewa, and ConnectIPS with a single API. Free to start.