Node framework quickstart

NestJS on Express payments without the scary bits

Pick your framework and only the relevant route code stays in view. Each framework has its own crawlable URL, so you can link straight to the docs your team needs.

Express

NestJS on Express

When NestJS runs on Express, mount the OpenReceive Express routes on the underlying app.

Server package
@openreceive/express
API mount
/openreceive/v1
Secret location
Server only

Common setup

First, get a receive-only NWC code so your server can create invoices and check payment status. You can switch NWC providers later without changing the browser checkout.

Server environment
OPENRECEIVE_NWC=nostr+walletconnect://...
OPENRECEIVE_STORE=local-sqlite
OPENRECEIVE_NAMESPACE=default

Use postgres://... for production storage, or sqlite:///abs/path/openreceive.sqlite3 for an explicit single-machine file. The store initializes itself on boot.

Install packages
npm install @openreceive/node @openreceive/express @openreceive/browser pg
Setup check
npx openreceive doctor

NestJS on Express server route

Live checkout always needs a server component. Browser code never receives OPENRECEIVE_NWC.

Use the same server/openreceive.ts config from the Express path, then mount it during framework boot.

Mount during bootstrap
import { NestFactory } from "@nestjs/core";
import { mountOpenReceiveExpressRoutes } from "@openreceive/express";
import { AppModule } from "./app.module";
import { openreceive } from "./server/openreceive";

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  mountOpenReceiveExpressRoutes(app.getHttpAdapter().getInstance(), openreceive);
  await app.listen(3000);
}

bootstrap();

Browser checkout

Your UI creates an invoice by posting to your OpenReceive server route.

Create an invoice
const response = await fetch("/openreceive/v1/invoices", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": orderId
  },
  body: JSON.stringify({
    fiat: {
      currency: "USD",
      value: "10.00"
    },
    metadata: {
      order_id: orderId
    }
  })
});

const invoice = await response.json();
React checkout UI
import { OpenReceiveCheckout } from "@openreceive/react";
import "@openreceive/react/styles.css";

export function Checkout({ invoice }) {
  return (
    <OpenReceiveCheckout
      {...invoice}
      lookupUrl="/openreceive/v1/invoices/lookup"
    />
  );
}

No-framework apps can use @openreceive/elements or lower-level @openreceive/browser helpers.

Recovery

OpenReceive does not need a daemon or wallet notification listener. Browser lookups and bounded route-triggered sweeps use backend invoice lookup, and an optional scheduler can run one extra recovery pass.

Processes
web                 npm start
optional scheduler  npx openreceive poll --once
One recovery pass
npx openreceive poll --once
Storage note: Production today should use package-owned Postgres storage. SQLite is for single-machine self-hosting, local development, demos, and small apps.