# Renderização de PDF > capabilities.pdf.render transforma HTML em PDF sem conhecer endpoint, credencial ou implementação — com limites, cancelamento e erros com retryable. ## 1. Declare a dependência Em `oon.deploy.json` (não em `central.app.json`): ```json title="oon.deploy.json" { "capabilities": { "pdfRendering": { "required": true, "minVersion": "1.0.0" } } } ``` Não adicione URL, usuário, senha ou implementation reference — o runtime resolve na publicação. ## 2. Crie a rota ```javascript title="backend/src/routes/pdf.js" const { capabilities, defineRoutes, GenericError } = require("@oondemand/oon-core-back"); defineRoutes("/pdf", (router) => { router.private.post("/render", { permission: "pdf.render" }, async (req, res) => { if (typeof req.body?.html !== "string" || !req.body.html.trim()) { throw new GenericError("Informe o HTML.", { statusCode: 422, code: "PDF_HTML_REQUIRED" }); } const controller = new AbortController(); const abort = () => controller.abort(); req.once("aborted", abort); res.once("close", abort); try { const pdf = await capabilities.pdf.render( { html: req.body.html, format: req.body.format || "A4", printBackground: true }, { ...req.accessContext, correlationId: req.correlationId, environment: process.env.APP_ENVIRONMENT, signal: controller.signal, }, ); res.type("application/pdf"); res.set("Content-Disposition", 'attachment; filename="documento.pdf"'); res.send(pdf); } finally { req.off("aborted", abort); res.off("close", abort); } }); }); ``` Declare `pdf.render` em `rbac.permissions` e conceda só aos perfis necessários. ## Assinatura ```ts capabilities.pdf.render(input, context): Promise ``` | `input` | Tipo | Regra / padrão | |---|---|---| | `html` | string | obrigatório; máximo padrão de 2 MiB | | `format` | `A3 \| A4 \| A5 \| Letter \| Legal` | `A4` | | `landscape` | boolean | `false` | | `marginTop/Bottom/Left/Right` | number | polegadas, 0 a 4; `0.39` | | `printBackground` | boolean | `true` | | `timeoutMs` | number | mín. 1.000; padrão 30.000; máx. do runtime 60.000 | `context` aceita `tenantId`, `appCode`, `environment`, `operationId`, `correlationId`/`requestId`, `signal` e, só em testes, `fetchImpl`. A saída começa com `%PDF-` e tem limite padrão de 20 MiB. O alias `capabilities.pdfRendering.render` é compatível. ## 3. Preview e download no frontend ```tsx