Blog
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
fetchand 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.tsdeclarations, 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/sdkTip: SetPAPERAPI_API_KEYandPAPERAPI_BASE_URLin.envor 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.tsfiles so the SDK slots into any bundler, library, or CLI. npm run typecheckandnpm run buildkeep 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
AbortSignalinstances, so you can cancel requests when jobs get rescheduled or time out.
Explore the SDK ecosystem
- Browse every PaperAPI SDK ->
- Read the source and follow releases on GitHub ->
- Deep-dive API docs, models, and examples ->
- Compare plans, EU-only regions, and support tiers ->
Questions about runtime coverage or roadmap priorities? Email founders@paperapi.de and we'll shape the next SDK drop together.
