@renduo/sdk
v0.0.3
Published
Official Renduo SDK — generate PDFs from registered component-first templates
Downloads
16
Maintainers
Readme
@renduo/sdk
Official TypeScript/Node SDK for Renduo — generate PDFs from templates you registered with renduo push (see @renduo/cli).
Types generated from the live API spec; the client itself is a small hand-written layer over native fetch — no runtime dependencies.
Install
npm install @renduo/sdkRequires Node ≥20 (native fetch, ESM only — see Module format below).
Need an API key? Free plan is 100 PDFs/month, no card required — see pricing and renduo.dev to sign up.
Quickstart
import { Renduo } from '@renduo/sdk'
import { writeFile } from 'node:fs/promises'
const renduo = new Renduo({ apiKey: process.env.RENDUO_API_KEY! })
const { pdf } = await renduo.generate({
templateId: 'tpl_...', // renduo templates list, or Dashboard → Templates
payload: { invoiceNumber: 'INV-001', customerName: 'Ada Lovelace' },
})
await writeFile('invoice.pdf', pdf)Async generation
For high volume or background jobs, use mode: 'async' and either poll with waitForGeneration or listen for the generation.completed webhook registered in Dashboard → Settings → Webhooks (see Verifying webhooks).
const job = await renduo.generate({ templateId: 'tpl_...', payload, mode: 'async' })
// job: { jobId, status: 'queued' }
const result = await renduo.waitForGeneration(job.jobId)
// result.pdf is a Buffer, same as sync mode — waitForGeneration polls
// GET /v1/generate/:jobId and downloads the PDF once it's ready.waitForGeneration throws RenduoGenerationError if the job ends in failed or timeout, with the job's errorMessage and status attached.
Templates
const { templates, total } = await renduo.templates.list()
const template = await renduo.templates.get(templates[0].id)
// template.versions: [{ version, status: 'active' | 'disabled', createdAt }, ...], newest firstVerifying webhooks
import { verifyWebhookSignature } from '@renduo/sdk'
const signature = request.headers.get('renduo-signature')
const rawBody = await request.text() // must be the raw body — not a re-serialized JSON.parse/stringify round trip
if (!verifyWebhookSignature(process.env.RENDUO_WEBHOOK_SECRET!, rawBody, signature!)) {
return new Response('Invalid signature', { status: 401 })
}Error handling
Every non-2xx response throws RenduoApiError — error/message/requestId from the API response, typed:
import { RenduoApiError } from '@renduo/sdk'
try {
await renduo.generate({ templateId, payload })
} catch (err) {
if (err instanceof RenduoApiError && err.code === 'QUOTA_EXCEEDED') {
// handle plan quota exhausted (free plan only — paid plans accumulate overage instead)
}
throw err
}Module format
ESM only, matching the rest of the Renduo monorepo. A CommonJS require('@renduo/sdk') won't work — use dynamic import('@renduo/sdk') from CommonJS code, or run your project as ESM ("type": "module" in package.json, or .mjs). Revisit if a real CJS consumer shows up; dual-publishing wasn't worth the added build complexity for a 0.x package with an all-TS/ESM audience.
Documentation
See renduo.dev/docs for the full API reference and guides.
