by Mateo Q.

Integrate Paddle Billing into server-side JavaScript applications with full TypeScript support. Manage subscriptions, payments, customers, products, and webhooks through one unified API.
This block delivers the official Paddle Billing Node.js SDK (@paddle/paddle-node-sdk@3.8.0) as a portable source drop-in. It exposes a typed client for managing products, prices, subscriptions, transactions, customers, adjustments, discounts, and more through the Paddle Billing API. Target buyers are backend TypeScript/Node.js teams who want full source visibility and version-locked control over the SDK without relying on live npm resolution.
entities/ - Typed entity classes for every Paddle resource (address, adjustment, business, customer, discount, subscription, transaction, etc.)enums/ - Enumeration constants used across API requests and responsesinternal/ - HTTP client, request serialization, response parsing, and error handling internalsnotifications/ - Webhook/notification payload parsing and signature verificationresources/ - One sub-module per API resource exposing CRUD and list operationstypes/ - TypeScript type definitions for request bodies, query parameters, and API responsesindex.cjs.edge.ts - CJS entry point for edge runtimesindex.cjs.node.ts - CJS entry point for standard Node.jsindex.esm.edge.ts - ESM entry point for edge runtimesindex.esm.node.ts - ESM entry point for standard Node.jspaddle.ts - Root Paddle class wiring all resources togethernpm install @paddle/paddle-node-sdk
No native modules, no pod install, no Android linking. Node.js 18+ is required for the native fetch API used internally. If you are on Node.js 16, polyfill fetch globally before constructing the client.
Copy the source/ directory into your project, for example at src/paddle-sdk/.
In tsconfig.json ensure moduleResolution is node16 or bundler and esModuleInterop is true:
{
"compilerOptions": {
"module": "NodeNext",
"moduleResolution": "NodeNext",
"esModuleInterop": true,
"strict": true
}
}
Spin up an isolated sandbox and run it server-side — no local setup.
Tetrees AI Review of this version
This TypeScript cli / script completed archive review. Structure, dependency manifests, documentation, functional source, and common risk patterns were checked by the Tetrees verification pipeline; runtime phases are stated separately.
Deterministic AVCP artifact review
Pipeline avcp-2026-08-04.1 · SHA-256 768865b746842a55…
This version-scoped review deterministically inspects the submitted archive for structure, dependencies, documentation, functional source, and common malicious or high-risk signals. Build and test phases are reported as passed only after an isolated sandbox audition. It is not a guarantee of perfect security.
Reviewed Aug 4, 2026
Push this product straight into your AI IDE, web builder or cloud IDE.
Connect Tetrees to a compatible AI IDE, list products you own, and request the verified ZIP without exposing seller upload controls.
No reviews yet.
Sign in to join the discussion
Loading discussion…
PADDLE_API_KEY=your_live_or_sandbox_key
PADDLE_ENV=sandbox # or production
Import from the local source or from the installed package. If using the source directly, point imports at src/paddle-sdk/paddle.ts and src/paddle-sdk/entities/index.ts. If you prefer the compiled package, import from @paddle/paddle-node-sdk as shown in the examples below; both resolve to identical code.
Instantiate the client once and export it as a singleton:
// src/lib/paddle.ts
import { Paddle, Environment, LogLevel } from '@paddle/paddle-node-sdk';
export const paddle = new Paddle(process.env.PADDLE_API_KEY!, {
environment:
process.env.PADDLE_ENV === 'production'
? Environment.production
: Environment.sandbox,
logLevel: LogLevel.error,
});
class Paddle {
constructor(apiKey: string, options?: {
environment?: Environment;
logLevel?: LogLevel;
customHeaders?: Record<string, string>;
});
products: ProductsResource;
prices: PricesResource;
customers: CustomersResource;
subscriptions: SubscriptionsResource;
transactions: TransactionsResource;
adjustments: AdjustmentsResource;
discounts: DiscountsResource;
addresses: AddressesResource;
businesses: BusinessesResource;
notifications: NotificationsResource;
// ...all other resources
}
The central client class. Instantiate once per process with your API key. Every Paddle resource is accessible as a property. Switch environment between Environment.sandbox and Environment.production to target different API endpoints.
export type CustomData = Record<string, any>;
A generic key-value map accepted on transactions, subscriptions, customers, and other entities as the customData field. Use it to attach your own business metadata (order IDs, user IDs, plan codes) to Paddle objects without requiring schema changes on Paddle's side.
enum Environment {
production = 'production',
sandbox = 'sandbox',
}
Passed to the Paddle constructor to control which Paddle API base URL is called. Always default to sandbox during development; switch to production only with live API keys. Sandbox and production API keys are not interchangeable.
Retrieve every subscription associated with a customer using the async iterator returned by list. Iterate with for await to transparently handle pagination.
import { paddle } from './lib/paddle';
async function getCustomerSubscriptions(customerId: string) {
const subscriptions = paddle.subscriptions.list({ customerId });
for await (const subscription of subscriptions) {
console.log(subscription.id, subscription.status, subscription.currentBillingPeriod);
}
}
getCustomerSubscriptions('ctm_01abc123').catch(console.error);
Build a one-time transaction for a customer with custom metadata so your system can correlate it with an internal order.
import { paddle } from './lib/paddle';
import type { CustomData } from '@paddle/paddle-node-sdk';
async function createOrder(customerId: string, priceId: string, internalOrderId: string) {
const customData: CustomData = { orderId: internalOrderId, source: 'api' };
const transaction = await paddle.transactions.create({
items: [{ priceId, quantity: 1 }],
customerId,
customData,
});
console.log('Transaction created:', transaction.id, transaction.status);
return transaction;
}
Use the notifications resource to verify Paddle's HMAC signature and deserialize the payload into a typed event entity before processing.
import express from 'express';
import { paddle } from './lib/paddle';
const app = express();
app.post(
'/webhooks/paddle',
express.raw({ type: 'application/json' }),
async (req, res) => {
const signature = req.headers['paddle-signature'] as string;
const rawBody = req.body.toString();
try {
const event = await paddle.notifications.unmarshal(
rawBody,
process.env.PADDLE_WEBHOOK_SECRET!,
signature,
);
switch (event.eventType) {
case 'subscription.activated':
console.log('Subscription activated:', event.data.id);
break;
case 'transaction.completed':
console.log('Transaction completed:', event.data.id);
break;
}
res.sendStatus(200);
} catch (err) {
console.error('Invalid webhook signature', err);
res.sendStatus(400);
}
},
);
paddle.ts - Instantiates all resource classes and wires them onto the Paddle client; the single entry point your application code should depend on.entities/ - Plain TypeScript classes that represent hydrated API response objects. Each sub-directory maps to one Paddle resource domain and exports a primary entity class plus a collection wrapper.entities/index.ts - Barrel re-export of every entity, collection, and the CustomData type alias; import from here to avoid deep path coupling.enums/ - Shared string enum constants (status values, action types, currency codes, etc.) used in both request and response types.internal/ - Private HTTP layer: fetch wrapper, pagination cursor logic, error class hierarchy, and response deserializer. Not intended for direct use.notifications/ - Webhook signature verification and event payload unmarshaling. Used server-side when receiving Paddle event callbacks.resources/ - One class per Paddle API resource with list, get, create, update, and resource-specific action methods.types/ - Request parameter interfaces and response shape types consumed by resource methods and entity constructors.index.cjs.node.ts / index.esm.node.ts - Node.js-targeted entry points (CJS and ESM). Use these when bundling for a standard Node.js server.index.cjs.edge.ts / index.esm.edge.ts - Edge-runtime entry points (Cloudflare Workers, Vercel Edge). Same surface area, different internal fetch adapter.Environment.sandbox returns 401. Always generate a dedicated sandbox key in the Paddle dashboard.fetch not defined on Node.js 16: The SDK uses native fetch; on Node 16 add import 'cross-fetch/polyfill' before constructing Paddle.paddle.subscriptions.list(...) returns an async iterator, not a Promise. Calling await on it does nothing useful; always use for await or call .next().snake_case vs camelCase mismatch: The Paddle API docs show snake_case field names; this SDK uses camelCase in both requests and responses. custom_data in docs → customData in SDK..js extension in source imports: The source files use .js extensions on relative imports for ESM compatibility. If you compile with tsc targeting CommonJS without moduleResolution: node16, these extensions may cause resolution failures. Set moduleResolution to node16 or bundler.Buffer for signature verification. Do not apply express.json() globally before the webhook route; use express.raw({ type: 'application/json' }) only on the webhook endpoint.I have dropped the Paddle Node.js SDK source into `src/paddle-sdk/` in my project.
The USAGE.md for this block is at `USAGE.md`. The upstream package is `@paddle/paddle-node-sdk@3.8.0`.
Please help me integrate it step by step:
1. Read `USAGE.md` and `src/paddle-sdk/paddle.ts` to understand the client API.
2. Create `src/lib/paddle.ts` that instantiates `Paddle` using environment variables
`PADDLE_API_KEY` and `PADDLE_ENV`.
3. Add a webhook handler in my Express app that uses `paddle.notifications.unmarshal`
to verify signatures and route events.
4. Add a service function that lists subscriptions for a given customerId using
`for await` over the async iterator.
5. Ensure all imports use the real exported symbols from `src/paddle-sdk/entities/index.ts`
and `src/paddle-sdk/paddle.ts`. Do not invent any method or type names.
6. Show me the required `tsconfig.json` changes and any env vars I need to add to `.env`.
The Paddle Node.js SDK is released under the MIT License. See the upstream repository at https://github.com/PaddleHQ/paddle-node-sdk and the published package at https://www.npmjs.com/package/@paddle/paddle-node-sdk for full license text and changelog.
This product’s unique contribution is clean room implementation of valuable code block into AVCP compatible standard.
The full install guide and integration prompts unlock after purchase.
SaaS, AI & Subscription Products
Free