0%
PRAXIUM LABS

Namaste! 🇳🇵

You found our hidden gem! Something incredible is brewing in the heart of the Himalayas. We might have something special here for you soon.

Stay curious. Jay Nepal!

Share

Khalti Webhook Integration with n8n: Production Recipe for Nepal (2026)

Khalti Webhook Integration with n8n: Production Recipe for Nepal (2026)

TL;DR. Khalti's KPG v2 differs from eSewa: there is no HMAC-signed callback. Instead, you call Khalti's lookup endpoint with the pidx (payment index) after the user returns to your site. The n8n workflow below verifies via lookup, idempotently marks the invoice paid, and pushes a WhatsApp receipt — usually under 1.5 seconds end-to-end.

At Praxium Labs we build this for Nepali businesses every month; this is the field-tested version. Khalti is Nepal's second-largest wallet by volume and the preferred gateway for many SaaS and education clients. KPG v2 is cleaner than eSewa's scheme, but the pitfalls are different — most production bugs come from skipping the lookup step or trusting the redirect query string.

How Khalti KPG v2 differs from eSewa

Khalti does not send a signed callback. After the user pays, Khalti redirects them back to your return_url with query params (pidx, status, txnId, amount, purchase_order_id). You must then call Khalti's lookup endpoint (POST https://khalti.com/api/v2/epayment/lookup/) to confirm the payment server-side. Trusting the query params alone is the #1 way fraud creeps in.

The n8n workflow

  • Webhook node: catches the return_url redirect
  • HTTP Request node: POST to lookup endpoint with pidx and your live secret key
  • IF node: proceed only if response.status == "Completed" and amount matches expected
  • Postgres / Sheets node: mark invoice paid (idempotently — use the pidx as the unique key)
  • WhatsApp node: send receipt
  • Error workflow: alert ops on any failure

The lookup call

HTTP Request node configuration

POST https://khalti.com/api/v2/epayment/lookup/
Authorization: Key {KHALTI_LIVE_SECRET}
Content-Type: application/json

{
  "pidx": "{{ $json.query.pidx }}"
}

Verify the response

// Function node after lookup
const r = $json;
if (r.status !== 'Completed') throw new Error('Khalti status: ' + r.status);
if (parseInt(r.total_amount) !== expectedAmountInPaisa) {
  throw new Error('Amount mismatch: ' + r.total_amount);
}
return { ...r, verified: true };

Idempotency

Customers click "Pay" buttons twice. Pages reload. Webhooks fire on page-back. Build the workflow so calling it ten times with the same pidx produces the same end state. The pattern: query your invoices table for the pidx first; only mark paid if it is not already marked. Use a unique constraint on pidx at the database level as the ultimate guard.

Currency precision in paisa

Khalti expresses amounts in paisa (NPR × 100). Always store amounts in paisa internally — a NPR 1,250.50 invoice is 125,050 paisa. Mixing rupee and paisa scales is a recurring bug in beginner integrations.

Handling cancelled and pending payments

A user who cancels redirects back with status=User canceled. A pending bank transfer can take 5–30 minutes; the redirect returns status=Pending. Your workflow needs three branches: Completed (mark paid), Pending (set status to awaiting, schedule a re-lookup in 10 minutes), Cancelled / Refunded (mark void, free reserved inventory).

Production deployment checklist

  • Use n8n with a public URL — Khalti needs to POST to a routable endpoint. Self-hosted n8n on a VPS + a Cloudflare-fronted domain works; see our self-hosted setup guide
  • Sign webhook URLs: include a long random secret in the URL path; reject calls without it
  • Reject replays: store pidx + timestamp; refuse the same pidx twice
  • Set explicit timeout on the verify call to Khalti's API (5 seconds); fall back to "pending" not "success" on timeout
  • Alert on workflow failures: n8n Slack / email notification on any execution error — payment workflows must not fail silently
  • Backup workflow state: export your workflows to git so a server failure does not lose the integration

Multi-currency considerations

Khalti is NPR-only at the gateway level. If your products are priced in USD (common for SaaS), convert to NPR at checkout time using a rate from an FX-rate API (Open Exchange Rates, ExchangeRate API). Round to the nearest NPR — Khalti does not accept paisa. Store both the USD and NPR amounts in your order record to reconcile against your USD-denominated accounting. For broader pricing strategy in NPR, see our SaaS pricing guide.

Frequently asked questions

Does Khalti send a webhook when payment is completed?

KPG v2 does not push webhooks for completion events in the same way eSewa does. The pattern is: user redirects to your return_url → you call lookup → you mark paid. For asynchronous flows (bank transfers that complete later), poll lookup every 10 minutes for pending pidx values.

Why call lookup at all if I trust the redirect?

Because the redirect query string is trivially forgeable — a malicious user can manually visit your return_url with status=Completed and a made-up pidx. The lookup call goes server-to-server with your authenticated key, so the response is trustworthy.

What does Khalti charge per transaction?

Standard merchant pricing as of 2026 is 2.55% per transaction with no monthly minimum. Volume-discounted rates exist above NPR 5 lakh/month — talk to Khalti merchant support.

Can I refund a Khalti payment via the API?

Yes — Khalti exposes a refund endpoint that takes the original pidx. Refunds settle in 1–3 working days. Build a separate n8n workflow for refunds triggered from an internal admin panel.

Does Khalti work in Khalti UAT for testing?

Yes — there is a separate sandbox at https://dev.khalti.com/api/v2/ with test keys. All development happens there.

How do I support both eSewa and Khalti in the same workflow?

Use a single "payments" workflow with two webhook endpoints — one for eSewa, one for Khalti — that converge on the same "mark invoice paid + notify customer" sub-workflow. The common shape makes adding Fonepay or ConnectIPS later straightforward — see our multi-gateway selector guide.

Does Khalti charge n8n calls extra?

No — Khalti's pricing is per transaction, not per API call. Workflow orchestration cost is yours (n8n VPS, monitoring), not Khalti's.

Can n8n handle Khalti subscriptions?

Khalti does not have first-class subscription primitives. To run subscriptions through Khalti, schedule a recurring n8n workflow that creates a fresh pidx each billing cycle and emails the customer a pay link. Less ideal than auto-debit, but functional.

Who can build this in Nepal?

Praxium Labs — Nepal's AI and automation consultancy, based in Lalitpur — designs and builds the systems described in this guide for Nepali businesses and for international teams hiring from Nepal. Start a project or see all services.