SDK Quick Start

Start with the documented V2 semantic protocol, then choose whether you want the hosted runtime or the self-hosted engine.

V2 Runtime Quick Start

TYPESCRIPT
const document = {
  version: "2.0",
  title: "Q3 Board Update",
  accentColor: "#2563EB",
  slides: [
    {
      slideType: "title-body",
      title: "Q3 Board Update",
      subtitle: "October 2025",
      body: [
        "Preflight findings are stable and machine-readable.",
        "Render jobs stay reviewable, comparable, and approvable."
      ],
    },
    {
      slideType: "kpi-grid",
      title: "Key Metrics",
      items: [
        { label: "ARR", value: "$4.2M", sublabel: "+18% QoQ", trend: "up" },
        { label: "NRR", value: "118%", sublabel: "Above target", trend: "up" },
        { label: "Burn", value: "$180K/mo", sublabel: "24mo runway", trend: "down" }
      ],
    },
    {
      slideType: "waterfall",
      title: "Revenue Growth",
      entries: [
        { label: "Q2 ARR", value: 4200, type: "total" },
        { label: "Expansion", value: 650, type: "increase" },
        { label: "Churn", value: -110, type: "decrease" },
        { label: "Q3 ARR", value: 4740, type: "total" }
      ],
    },
  ],
};

const preflight = await fetch("https://api.paperjsx.com/api/v2/preflight", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PAPERJSX_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    sourceSchema: "protocol_v2",
    preflightPolicy: { autoFix: "suggest_only" },
    document,
  }),
});

const render = await fetch("https://api.paperjsx.com/api/v2/render", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PAPERJSX_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    sourceSchema: "protocol_v2",
    mode: "async",
    approvalRequired: true,
    preflightPolicy: { renderIfScoreAbove: 70, autoFix: "suggest_only" },
    document,
  }),
});

const { data } = await render.json();
console.log(data.job_id, data.job_url);

Self-Hosted Engine

If you run @paperjsx/pptx-core on your own infrastructure, the engine consumes PaperDocument AST directly. That path is optimized for self-hosted rendering and advanced control. In this phase, @paperjsx/pptx-core is the supported self-hosted package surface.

TYPESCRIPT
import { CmdCal } from "@paperjsx/pptx-core";
import fs from "node:fs";

const engine = new CmdCal({
  licenseKey: process.env.PAPERJSX_KEY!,
});

const pptx = await engine.renderDocument({
  type: "Document",
  meta: { title: "Self-hosted Render" },
  slides: [
    {
      type: "Slide",
      children: [
        {
          type: "Text",
          content: "Hello from the self-hosted engine",
          style: { x: 80, y: 80, width: 700, fontSize: 28, fontWeight: "bold" },
        },
      ],
    },
  ],
});

fs.writeFileSync("self-hosted-render.pptx", pptx);

Legacy Compatibility

AgentDocument remains available for compatibility, but it is no longer the default public contract. Use it only when you are maintaining an older integration that still depends on slide pattern payloads.

With Previews

TYPESCRIPT
const { pptx, previews } = await engine.generateWithPreviews(document);

// previews is Buffer[] — one PNG per slide
previews.forEach((png, i) => {
  fs.writeFileSync(`slide-${i + 1}.png`, png);
});

Error Handling

TYPESCRIPT
try {
  const pptx = await engine.generate(document);
} catch (err) {
  if (err.message.includes("license")) {
    // License validation failed
    console.error("Check your PAPERJSX_KEY");
  } else {
    // Render error
    console.error("Generation failed:", err.message);
  }
}