TypeScript SDK
@pptx/sdk for TypeScript
Typed client for the pptx.dev REST API. Works in Node 20+, Next.js (App Router, server + client), Bun, and modern browsers. Ships OPF document types, typed errors, and a dual ESM / CJS build.
Install
Shell
npm i @pptx/sdk # or pnpm add @pptx/sdk # or bun add @pptx/sdk
First call
Create a client with your API key and validate an OPF document. Validation is always free.
TypeScript
import { PptxClient } from "@pptx/sdk";
const pptx = new PptxClient({ apiKey: process.env.PPTX_API_KEY });
const result = await pptx.opf.validate({
$schema: "https://pptx.dev/schema/opf/v1",
version: "1.0",
meta: { title: "Hello" },
design: { theme: "corporate-minimal" },
slides: [
{
id: "s1",
layout: "title-slide",
elements: [
{ id: "h1", type: "text", content: { text: "Hello, world" } },
],
},
],
});
console.log(result.valid, result.errors, result.warnings);Authentication
The client resolves a bearer token in this order:
- The
apiKeyoption passed to the constructor. - The
PPTX_API_KEYenvironment variable (Node / Bun runtimes only).
TypeScript
import { PptxClient } from "@pptx/sdk";
const pptx = new PptxClient({ apiKey: "ppx_..." });Get your API key from the API Keys page.
Generate a .pptx from OPF
TypeScript
import { PptxClient, type OPFDocument } from "@pptx/sdk";
const pptx = new PptxClient();
const doc: OPFDocument = {
$schema: "https://pptx.dev/schema/opf/v1",
version: "1.0",
meta: { title: "Q1 Review" },
design: { theme: "corporate-minimal" },
slides: [
{
id: "title",
layout: "title-slide",
elements: [
{ id: "h1", type: "text", content: { text: "Q1 Review" } },
],
},
],
};
const job = await pptx.opf.generate(doc, { format: "pptx" });
console.log(job.status, job.slideCount);Parse an existing .pptx
TypeScript
import { readFile } from "node:fs/promises";
import { PptxClient } from "@pptx/sdk";
const pptx = new PptxClient();
const bytes = await readFile("deck.pptx");
const { parseId, slideCount } = await pptx.parse.upload({
data: bytes,
filename: "deck.pptx",
});
const slide0 = await pptx.parse.slide(parseId, 0);
console.log(slide0.textRuns);Error handling
All errors extend PptxError.
| Error | When |
|---|---|
| PptxNetworkError | fetch threw (DNS, TLS, timeout, aborted) |
| PptxApiError | HTTP 4xx / 5xx response with JSON or text body |
| PptxValidationError | HTTP 422 with validationErrors[] from opf.generate |
| PptxRateLimitError | HTTP 429 (exposes retryAfterSeconds) |
TypeScript
import {
PptxValidationError,
PptxRateLimitError,
} from "@pptx/sdk";
try {
await pptx.opf.generate(badDoc);
} catch (err) {
if (err instanceof PptxValidationError) {
console.error("OPF schema errors:", err.validationErrors);
} else if (err instanceof PptxRateLimitError) {
console.error("Retry after:", err.retryAfterSeconds, "s");
} else {
throw err;
}
}Every error exposes requestId when the server returned an X-Request-Id header.
OPF types
The full OPF type tree is available from the root entry or the /opf subpath.
TypeScript
import type { OPFDocument, OPFSlide, OPFElement } from "@pptx/sdk";
// or
import type { OPFDocument } from "@pptx/sdk/opf";Custom base URL
For local development against a Next.js dev server:
TypeScript
const pptx = new PptxClient({
baseUrl: "http://localhost:3000/api",
});