Blog

PaperAPI npm SDK is live on npm

Dec 30, 2025
sdksjavascript
PaperAPI npm SDK is live on npm

JavaScript teams no longer need to wire raw HTTP calls just to turn HTML into PDFs. The PaperAPI npm SDK ships today with first-class TypeScript types, runtime validation, and a fetch-first architecture that runs anywhere from Node 18+ to edge workers and modern browsers.

Why JavaScript teams asked for this launch

  • Fetch-native design that reuses your platform's fetch and only asks for a custom implementation when you're on Node < 18.
  • Typed requests/responses backed by zod, so schema drift shows up immediately in both TypeScript and runtime validation.
  • PaperApiError surface that bundles HTTP status, error codes, x-request-id, and the raw body for better logging and retries.
  • ESM + CJS output with .d.ts declarations, keeping bundlers happy while still fitting CommonJS projects.
  • Minimal dependencies (just zod) plus customizable user agents so regulated workloads stay lean and auditable.

Source, CI workflows, and release automation all live in github.com/paperapi, so you can inspect every change and open issues next to the SDK code itself.

Install from npm in seconds

Grab the package from npm and keep your API keys in environment variables:

npm install @paperapi/sdk
# or
pnpm add @paperapi/sdk
Tip: Set PAPERAPI_API_KEY and PAPERAPI_BASE_URL in .env or your secrets manager so local dev, staging, and production share the exact same configuration.

Render your first PDF with PaperApiClient

import { PaperApiClient } from "@paperapi/sdk";
import { writeFile } from "node:fs/promises";

const client = new PaperApiClient({
  apiKey: process.env.PAPERAPI_API_KEY!,
  baseUrl: process.env.PAPERAPI_BASE_URL, // defaults to https://api.paperapi.de/
  userAgent: "BillingService/1.4.3",
});

const pdf = await client.generatePdf({
  html: "<html><body><h1>PaperAPI <3 TypeScript</h1></body></html>",
  options: {
    pageSize: "A4",
    marginTop: 5,
    marginBottom: 5,
  },
});

await writeFile("invoice.pdf", Buffer.from(pdf));

Swap generatePdf for enqueuePdfJob any time you want the API to queue heavy renders while your worker polls for completion.

Async jobs, usage, and metadata from one client

const job = await client.enqueuePdfJob({ html: "<h1>Async job</h1>" });
console.log(job.status, job.links.self);

const refreshed = await client.getJobStatus(job.id);
if (refreshed.downloadUrl) {
  const result = await client.downloadJobResult(job.id);
  await writeFile("job.pdf", Buffer.from(result));
}

const usage = await client.getUsageSummary();
console.log(`Used ${usage.used}/${usage.monthlyLimit} PDFs, next reset ${usage.nextRechargeAt}`);

const profile = await client.getWhoAmI();
console.log(`Authenticated as ${profile.email} (${profile.plan.name})`);

Health checks (checkHealth) and metadata (getWhoAmI) live next to the PDF methods, so your observability hooks don't need a second HTTP client.

Fail loud, retry smart

Every non-2xx response throws PaperApiError with enough context to power alerts and retries:

import { PaperApiError } from "@paperapi/sdk";

try {
  await client.generatePdf({ html: "" });
} catch (error) {
  if (error instanceof PaperApiError) {
    console.error({
      status: error.status,
      requestId: error.requestId,
      errorCode: error.errorCode,
      body: error.responseBody,
    });
  }
}

You can feed error.requestId into PaperAPI support, or bubble it into your logs to trace failures across services.

Production ready from day one

  • Bundled ESM/CJS builds plus .d.ts files so the SDK slots into any bundler, library, or CLI.
  • npm run typecheck and npm run build keep CI honest before you publish.
  • The default user agent (PaperApiJsSdk/0.1.x) is overrideable, letting you add app/version fingerprints for upstream debugging.
  • Queue-friendly APIs accept AbortSignal instances, so you can cancel requests when jobs get rescheduled or time out.

Explore the SDK ecosystem

Questions about runtime coverage or roadmap priorities? Email founders@paperapi.de and we'll shape the next SDK drop together.