Installation

@forjio/plugipay-node is a single npm package with zero runtime dependencies. This page covers installing it, which Node versions work, ESM vs. CommonJS, TypeScript setup, and what to expect from bundlers.

Install

npm install @forjio/plugipay-node

Or with your preferred package manager:

pnpm add @forjio/plugipay-node
yarn add @forjio/plugipay-node
bun add @forjio/plugipay-node

The package ships pre-built — you don't need a TypeScript or tsup toolchain to consume it.

Version requirements

Requirement Minimum
Node.js >=20.0.0
TypeScript (if you use it) >=5.0

Node 20 is the floor because the SDK uses the global fetch, AbortController, and crypto.randomUUID() — all stable in Node 20 LTS. Older Node versions (18, 16) are not tested and not supported.

Browser usage is not supported. The SDK imports from node:crypto and is designed to hold a long-lived secret — both of which are wrong for a browser context. If you need to call Plugipay from a browser, build a thin server-side proxy in Node and have the browser call that proxy.

ESM vs CommonJS

The package ships both flavors:

Entry File Used when
import dist/index.js Your project is ESM ("type": "module") or uses import syntax.
require dist/index.cjs Your project is CommonJS.
Types dist/index.d.ts Always — same file for both.

Both are produced from the same source — behavior is identical. Pick whichever matches your project.

ESM:

import { PlugipayClient, verifyWebhook, PlugipayError } from '@forjio/plugipay-node';

CommonJS:

const { PlugipayClient, verifyWebhook, PlugipayError } = require('@forjio/plugipay-node');

Both forms expose exactly the same surface.

"type": "module" is optional. The SDK works the same way in a classic CommonJS project as in a fully-ESM one. Pick what's consistent with the rest of your codebase — don't switch on the SDK's behalf.

TypeScript

The package ships its own .d.ts files — you don't need a separate @types/... install. After npm install, your editor should immediately pick up:

  • PlugipayClient and PlugipayClientOptions
  • Every resource input shape (e.g. the argument to customers.create)
  • Every resource return type (Customer, CheckoutSession, Invoice, ...)
  • The WebhookEvent discriminated union
  • PlugipayError

The recommended tsconfig.json settings:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true
  }
}

module: "NodeNext" is the safest choice — it picks the right entry (ESM vs CJS) automatically based on your package's "type" field.

Turn on strict. The SDK types are exhaustive; you'll catch optional-field mistakes (e.g. forgetting that customer.email can be null) at compile time rather than at runtime.

Tree-shaking

The SDK is structured as a single PlugipayClient class with all resources as instance properties. Tree-shaking works at the import boundary:

import { PlugipayClient } from '@forjio/plugipay-node';
// `verifyWebhook` and `PlugipayError` are not included in the bundle.

If you only need the webhook verifier (e.g. in a small webhook receiver), import just that:

import { verifyWebhook } from '@forjio/plugipay-node';
// `PlugipayClient` and all resource types are not bundled.

The whole library is under 10 KB minified. Tree-shaking helps marginally; don't optimize prematurely.

Bundling

For server runtimes (raw Node, Fastify, Express, NestJS), no bundling is needed — install and run.

For serverless / edge bundlers (esbuild, swc, webpack, Vercel, AWS Lambda, Cloudflare Workers), a few notes:

  • Cloudflare Workers / Deno / Bun edge runtimes. These don't expose node:crypto. The SDK won't run there. Stick to Node-compatible runtimes (Lambda Node 20 runtime, Vercel Functions Node 20 runtime, Cloud Run, Fly, regular Docker, etc.).
  • AWS Lambda. Works out of the box on the Node 20 runtime. Don't shim fetch — use the native one.
  • esbuild. Set platform: 'node' and target: 'node20'. The SDK doesn't need polyfills.
  • Webpack. Don't shim node:crypto. Externalize it or let webpack 5's built-in Node target handle it.

If you see Cannot find module 'node:crypto' at runtime, you're targeting a non-Node runtime. Switch back to a Node-compatible target.

Verifying the install

A one-line smoke test that the package resolved and exports look right:

import { PlugipayClient } from '@forjio/plugipay-node';
console.log(typeof PlugipayClient); // → "function"

To check end-to-end connectivity against your account, see Quickstart.

Upgrading

The SDK follows semantic versioning. For 0.x releases (where we are today), minor bumps may include small breaking changes — each is documented in the changelog.

Pin a caret range and review the changelog before bumping the minor:

{
  "dependencies": {
    "@forjio/plugipay-node": "^0.5.0"
  }
}

After 1.0 (target: mid-2026), the major/minor/patch contract becomes strict and you can rely on ^1.x.x unconditionally.

Troubleshooting

ERR_REQUIRE_ESM

You're using require('@forjio/plugipay-node') from an ESM context, or vice versa. Check your project's "type" field in package.json and use the matching import syntax.

fetch is not defined

You're on Node <18. Upgrade to Node 20+ — the SDK doesn't ship a fetch polyfill.

Cannot find module 'node:crypto'

You're bundling for a non-Node runtime (Cloudflare Workers, browser, Deno edge). The SDK isn't compatible with those. Use a Node-compatible runtime.

TypeScript can't find the types

Make sure your tsconfig.json uses "moduleResolution": "NodeNext" (or "Bundler"). The package's exports field uses conditional resolution, which only works with modern resolvers.

Next

Plugipay — Payments that don't tax your success