API

JavaScript PDF Generation SDK

The official @cloudlayerio/sdk provides JavaScript PDF generation for Node.js, Bun, and browser environments. Convert HTML to PDF, capture URLs as documents, and render templates — with full TypeScript type safety, zero runtime dependencies, and dual ESM/CJS support.

Installation

npm install @cloudlayerio/sdk
yarn add @cloudlayerio/sdk
pnpm add @cloudlayerio/sdk

Requirements: Node.js 20+ (uses native fetch) or any modern browser.

Setup

Get your API key by creating a free account at cloudlayer.io. Your account comes with free API credits for testing.

import { CloudLayer } from "@cloudlayerio/sdk";

const client = new CloudLayer({
  apiKey: "<YOUR-API-KEY>",
  apiVersion: "v2",
});

The SDK requires you to choose an API version:

v1v2
Default modeSynchronous (returns binary)Asynchronous (returns Job)
Sync responseRaw binary (PDF/image)JSON Job object
Binary accessDirect from responseVia downloadJobResult()

URL to PDF

v2 returns a Job object. Use downloadJobResult() to get the binary:

const { data: job } = await client.urlToPdf({
  url: "https://example.com",
  format: "a4",
  margin: { top: "20px", bottom: "20px" },
});

// Download the PDF binary
const pdfBuffer = await client.downloadJobResult(job);

v1 (legacy)

v1 returns the binary directly:

const v1 = new CloudLayer({ apiKey: "<YOUR-API-KEY>", apiVersion: "v1" });

const { data: pdfBuffer } = await v1.urlToPdf({
  url: "https://example.com",
});

URL to Image

const { data } = await client.urlToImage({
  url: "https://example.com",
  imageType: "png",
  quality: 90,
});

HTML to PDF

HTML content must be Base64-encoded:

const html = btoa("<html><body><h1>Hello World</h1></body></html>");

const { data: job } = await client.htmlToPdf({ html });

HTML to Image

const html = btoa("<html><body><h1>Screenshot</h1></body></html>");

const { data } = await client.htmlToImage({
  html,
  imageType: "webp",
  quality: 85,
});

Template to PDF

const { data: job } = await client.templateToPdf({
  templateId: "professional-invoice",
  data: {
    company_name: "Acme Inc.",
    invoice_no: "INV-001",
    items: [{ title: "Web Design", quantity: 10, unit_price: 150.0 }],
  },
});

File Conversion

import { readFileSync } from "node:fs";

// DOCX to PDF
const { data } = await client.docxToPdf({
  file: readFileSync("document.docx"),
});

// PDF to DOCX
const { data: docx } = await client.pdfToDocx({
  file: readFileSync("document.pdf"),
});

PDF Merge

const { data: job } = await client.mergePdfs({
  batch: {
    urls: [
      "https://example.com/page1.pdf",
      "https://example.com/page2.pdf",
    ],
  },
});

Batch Processing

Process up to 20 URLs in one request (always async):

const { data: job } = await client.urlToPdf({
  batch: {
    urls: ["https://a.com", "https://b.com", "https://c.com"],
  },
  storage: true,
});

Async Mode & Job Polling

const { data: job } = await client.urlToPdf({
  url: "https://example.com",
  storage: true,
});

// Poll until complete (5s interval, 5 min timeout)
const completed = await client.waitForJob(job.id);

// Download the result
const pdf = await client.downloadJobResult(completed);

Data Management

// Jobs
const jobs = await client.listJobs();
const job = await client.getJob("job-id");

// Assets
const assets = await client.listAssets();
const asset = await client.getAsset("asset-id");

// Storage
const storages = await client.listStorage();
await client.addStorage({
  title: "My S3",
  region: "us-east-1",
  accessKeyId: "AKIA...",
  secretAccessKey: "...",
  bucket: "my-bucket",
});

// Account
const account = await client.getAccount();
const status = await client.getStatus();

Error Handling

import {
  CloudLayerAuthError,
  CloudLayerRateLimitError,
  CloudLayerApiError,
  CloudLayerTimeoutError,
  CloudLayerValidationError,
} from "@cloudlayerio/sdk";

try {
  await client.urlToPdf({ url: "https://example.com" });
} catch (error) {
  if (error instanceof CloudLayerAuthError) {
    console.error("Invalid API key");
  } else if (error instanceof CloudLayerRateLimitError) {
    console.error(`Rate limited. Retry after ${error.retryAfter}s`);
  } else if (error instanceof CloudLayerApiError) {
    console.error(`API error ${error.status}: ${error.message}`);
  } else if (error instanceof CloudLayerTimeoutError) {
    console.error(`Timed out after ${error.timeout}ms`);
  } else if (error instanceof CloudLayerValidationError) {
    console.error(`Invalid input: ${error.field}`);
  }
}

Advanced Options

Viewport & Puppeteer

const { data } = await client.urlToPdf({
  url: "https://example.com",
  viewPort: {
    width: 1920,
    height: 1080,
    deviceScaleFactor: 2,
    isMobile: false,
    hasTouch: false,
    isLandscape: false,
  },
  waitUntil: "networkidle0",
  cookies: [{ name: "session", value: "abc123", domain: "example.com" }],
  authentication: { username: "user", password: "pass" },
});

Custom Margins & Headers/Footers

const { data } = await client.urlToPdf({
  url: "https://example.com",
  format: "letter",
  margin: { top: "1in", bottom: "1in", left: "0.5in", right: "0.5in" },
  printBackground: true,
  headerTemplate: {
    method: "extract",
    selector: ".page-header",
  },
  footerTemplate: {
    method: "template",
    template: "<div style='font-size:10px;text-align:center;width:100%'>Page <span class='pageNumber'></span></div>",
  },
});

TypeScript

Full type safety for all request options and responses:

import type {
  UrlToPdfOptions,
  Job,
  AccountInfo,
  CloudLayerResponseHeaders,
} from "@cloudlayerio/sdk";