A payments API for Nepal that you can read in an afternoon.

One call creates a checkout for eSewa, Khalti and Fonepay. We handle each gateway's signing, redirects and verification, then tell your server with a signed webhook.

Test mode with a Sandbox gateway is free. The full docs open after you sign in.

import Paymentsnp from "@paymentsnp/sdk";

const pnp = new Paymentsnp({ apiKey: process.env.PAYMENTSNP_API_KEY! });

// 1. Create a checkout (NPR 1,500.00 = 150000 paisa)
const session = await pnp.checkout.sessions.create(
  { order_id: "order-1001", amount_minor: 150000, currency: "NPR",
    success_url: "https://shop.example.com/orders/1001" },
  { idempotencyKey: "order-1001" },
);
// Redirect the customer to session.checkout_url

// 2. Webhook route: pass the raw body, not parsed JSON
const event = await Paymentsnp.webhooks.constructEvent(
  rawBody, req.get("Paymentnp-Signature"), process.env.PAYMENTSNP_WEBHOOK_SECRET!,
); // throws SignatureVerificationError if forged or stale
if (event.type === "payment.succeeded") fulfilOnce(event.id, event.data);
Server-side only. Keep your secret key out of browser code.

The whole flow

Same three steps for every gateway, in test and in live.

  1. Your server creates a checkout

    Send an order ID and an amount in paisa with your secret key and an Idempotency-Key. You get a checkout_url back. Retrying with the same key returns the same checkout.

  2. The customer pays

    Redirect them, or open the page in a popup with checkout.js. They choose a method and pay in the provider's own app.

    • eSewa
    • Khalti
    • Fonepay
  3. You get a verified webhook

    After the provider confirms the exact amount, we POST payment.succeeded to your endpoint. Verify the signature, then fulfil the order once per event ID.

POST /your/webhook  HTTP/1.1
Paymentnp-Signature: t=1791100000,v1=5f2c…
Paymentnp-Event-Id: 8f4f7c0e-2b1d-4a7e-9c55-0d3e1f6a9b21

{
  "id": "8f4f7c0e-2b1d-4a7e-9c55-0d3e1f6a9b21",
  "type": "payment.succeeded",
  "api_version": "v1",
  "environment": "test",
  "created_at": "2026-10-01T06:45:05.000Z",
  "data": {
    "payment_id": "5b2d6c1e-…",
    "checkout_session_id": "c1a94d07-…",
    "order_id": "order-1001",
    "provider": "esewa",
    "provider_transaction_id": "000AB12",
    "amount_minor": 150000,
    "currency": "NPR",
    "is_simulated": false,
    "overpaid": false
  }
}
Abridged. The developer guide has the full event shape and signature check.

The API at a glance

REST over HTTPS with JSON. Amounts are integer paisa. Every key is either test or live and carries only the scopes you give it.

  • Idempotent checkout creation, safe to retry
  • Webhooks signed with HMAC-SHA256, retried up to 8 times, replayable
  • Keys with scopes, expiry, rolling with a grace period, IP allowlists and per-key rate limits
  • Test mode only sees test data; the Sandbox gateway simulates success and failure
  • Unclear gateway answers stay pending, never paid by guesswork
Some of the API-key routes
MethodRouteScope
POST/v1/checkout/sessionscheckout:create
GET/v1/checkout/sessions/:idcheckout:read
POST/v1/checkout/sessions/:id/expirecheckout:create
GET/v1/paymentspayments:read
GET/v1/payments/:idpayments:read
GET/v1/invoicesinvoices:read
POST/v1/invoicesinvoices:write
POST/v1/invoices/:id/finalizeinvoices:write
POST/v1/invoices/:id/sendinvoices:write
POST/v1/reconciliation/import/bulkreconciliation:write
GET/v1/reconciliation/reportreconciliation:read

SDKs, CLI and MCP server

Official, zero-dependency libraries with typed errors, retries and webhook verification. Same method names in every language.

LanguageRegistryInstallNotes
TypeScript / Node.jsnpmnpm install @paymentsnp/sdkNode 18+, Bun, Deno, edge runtimes; includes the paymentsnp CLI
PHPPackagistcomposer require paymentsnp/paymentsnp-phpPHP 7.4+, curl and json only; works without Composer too
PythonPyPIpip install paymentsnpPython 3.9+, standard library only
MCP servernpmnpx -y @paymentsnp/mcpLets Claude, Cursor and other assistants read your payments; read-only unless you allow writes
A software developer writing code at a desk with two monitors

Plugins if you would rather not write code

Download them from the dashboard. Each one completes an order only after Paymentsnp verifies the payment.

WHMCSGateway module v3 pays WHMCS invoices with eSewa, Khalti and Fonepay, and upgrades v2 installs in place.
WooCommerceAdds Paymentsnp as a payment method, including the block checkout and HPOS stores.
ShopifyA self-hosted app that sends customers a pay link and marks the order paid once verified. Shopify only lets approved partners inside its checkout, so it uses a manual payment method.
No websitePayment links take a payment with no code at all.

A redirect is not a receipt

Your success_url tells you the customer came back. It does not tell you they paid. Fulfil on the webhook, or fetch the session.

  • Money settles directly to your own eSewa, Khalti and Fonepay merchant accounts.
  • Every payment is verified server-side with the gateway, for the exact amount.
  • API key secrets are shown once and stored only as a hash.
  • More on how we handle money and data on the security page.