This PDF has custom CSS styling.
openapi: 3.0.3 info: title: 3renderers PDF API description: | API for converting HTML/Markdown to PDF using three open-source rendering engines: Paged.js, WeasyPrint, and Vivliostyle. **3renderers** supports three open-source tools [Paged.js](https://pagedjs.org/), [WeasyPrint](https://weasyprint.org/), and [Vivliostyle](https://vivliostyle.org/). The service allows you to create PDFs from your HTML/Markdown and CSS source free of cost. **Please be aware that there is no guarantee that this service will be available or that the current rate limits and monthly traffic restrictions will stay the same.** Once the monthly max. traffic is reached, the service will return an error message. On the first of each month, the limit is reset, and you will be able to render more PDFs. If you want to avoid the traffic and rate limits, you can host this service yourself. The code is available under the MIT license ([https://github.com/CSS-Paged-Media/3renderers](https://github.com/CSS-Paged-Media/3renderers)). version: 1.0.0 contact: url: https://github.com/CSS-Paged-Media/3renderers license: name: MIT url: https://github.com/CSS-Paged-Media/3renderers/blob/main/LICENSE servers: - url: https://3renderers.dev description: Production server tags: - name: Rendering description: PDF rendering endpoints - name: Monitoring description: Service health and metrics endpoints paths: /api/render: post: tags: - Rendering summary: Render HTML or Markdown to PDF description: | Convert HTML or Markdown content to PDF. Supports both synchronous and asynchronous rendering. **Note:** You must provide either `html` OR `markdown`, but not both. If rendering asynchronously, you'll receive a `pdfid` to check the job status. For checking async job status, send a request with only the `pdfid` field. operationId: renderPDF requestBody: required: true content: application/json: schema: oneOf: - $ref: '#/components/schemas/RenderRequest' - $ref: '#/components/schemas/JobStatusRequest' examples: simpleHTML: summary: Simple HTML to PDF (Sync) value: html: "
This is a simple HTML to PDF conversion.
" options: renderer: "weasyprint" sync: "true" htmlWithCSS: summary: HTML with CSS (Sync) value: html: "This PDF has custom CSS styling.
Invoice #: {{ invoice_number }}
" css: "body { font-family: Arial, sans-serif; padding: 40px; }" data: - customer_name: "John Doe" invoice_number: "INV-2025-001" date: "2025-10-23" amount: "1250.00" options: renderer: "weasyprint" sync: "true" templateMultipleData: summary: Template with Multiple Data Objects (Batch) value: html: "Course: {{ course }}
" data: - name: "Alice Johnson" course: "Advanced TypeScript" - name: "Bob Smith" course: "Advanced TypeScript" options: renderer: "weasyprint" sync: "true" asyncRendering: summary: Async Rendering - Start Job value: html: "This PDF is being generated asynchronously.
" css: "body { font-family: Arial, sans-serif; padding: 40px; }" options: renderer: "weasyprint" sync: "false" checkJobStatus: summary: Check Async Job Status value: pdfid: "5bd48a77-30a8-4d15-bb99-48b55995592c" withAssets: summary: HTML with Assets ZIP value: html: "
"
css: "body { color: red; }"
assets: "UEsDSYkSE8mCCCF4IHXYab/C+q2RZnG39vKAAAAAElFTkSuQmCC..."
options:
renderer: "weasyprint"
sync: "true"
responses:
'200':
description: Successful response
content:
application/pdf:
schema:
type: string
format: binary
example: "PDF binary content"
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/AsyncJobResponse'
- $ref: '#/components/schemas/JobStatusResponse'
examples:
asyncJobStarted:
summary: Async job started
value:
pdfid: "5bd48a77-30a8-4d15-bb99-48b55995592c"
jobProcessing:
summary: Job still processing
value:
status: "processing"
message: "PDF is being generated"
headers:
x-ratelimit-limit:
schema:
type: integer
description: Request limit per minute
example: 60
x-ratelimit-remaining:
schema:
type: integer
description: Remaining requests in current window
example: 59
x-ratelimit-reset:
schema:
type: integer
description: Seconds until rate limit resets
example: 60
'400':
description: Bad Request - Invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
examples:
missingHTML:
summary: Missing required HTML field
value:
message: "Required \"html\" Key not found in Body"
invalidRenderer:
summary: Invalid renderer option
value:
message: "Invalid Renderer Option passed, valid options are \"weasyprint\", \"pagedjs\", and \"vivliostyle\""
javascriptNotSupported:
summary: JavaScript with WeasyPrint
value:
message: "Invalid Renderer Option passed, as the renderer does not support JavaScript use \"pagedjs\", or \"vivliostyle\" as renderer"
invalidPdfId:
summary: Invalid PDF ID
value:
pdfid: "invalid-pdf-id-12345"
status: "error"
message: "pdfid invalid"
bothHtmlAndMarkdown:
summary: Both HTML and Markdown provided
value:
message: "Exactly one of \"html\" or \"markdown\" must be provided"
headers:
x-ratelimit-limit:
schema:
type: integer
description: Request limit per minute
example: 60
x-ratelimit-remaining:
schema:
type: integer
description: Remaining requests in current window
example: 59
x-ratelimit-reset:
schema:
type: integer
description: Seconds until rate limit resets
example: 60
/health:
get:
tags:
- Monitoring
summary: Health Check
description: Check if the service and its dependencies are healthy
operationId: healthCheck
responses:
'200':
description: Service is healthy
headers:
x-ratelimit-limit:
schema:
type: integer
description: Request limit per minute
example: 60
x-ratelimit-remaining:
schema:
type: integer
description: Remaining requests in current window
example: 59
x-ratelimit-reset:
schema:
type: integer
description: Seconds until rate limit resets
example: 60
content:
application/json:
schema:
$ref: '#/components/schemas/HealthResponse'
example:
status: "healthy"
timestamp: "2025-10-23T14:34:38.912Z"
services:
database: "ok"
redis: "ok"
api: "ok"
/api/traffic-status:
get:
tags:
- Monitoring
summary: Traffic Usage Status
description: Check current traffic usage against monthly limits
operationId: trafficStatus
responses:
'200':
description: Traffic usage information
headers:
x-ratelimit-limit:
schema:
type: integer
example: 60
x-ratelimit-remaining:
schema:
type: integer
example: 59
x-ratelimit-reset:
schema:
type: integer
example: 60
content:
application/json:
schema:
$ref: '#/components/schemas/TrafficStatusResponse'
example:
usage:
bytes: 238277
gb: 0
percent: 0
tb: 0
remaining:
bytes: 20890720689467
gb: 19456
limit:
bytes: 20890720927744
gb: 19456
tb: 20
status: "OK"
resetDate: "2025-11-01"
/api/metrics/pdf:
get:
tags:
- Monitoring
summary: PDF Generation Metrics
description: Get counts of PDFs generated (total, week, month)
operationId: pdfMetrics
responses:
'200':
description: PDF generation metrics
headers:
x-ratelimit-limit:
schema:
type: integer
example: 60
x-ratelimit-remaining:
schema:
type: integer
example: 59
x-ratelimit-reset:
schema:
type: integer
example: 60
content:
application/json:
schema:
$ref: '#/components/schemas/MetricsResponse'
example:
counts:
total: 23
week: 23
month: 23
components:
schemas:
RenderRequest:
type: object
properties:
html:
type: string
description: HTML content to render (mutually exclusive with markdown)
example: "This is a test.
" markdown: type: string description: Markdown content to render (mutually exclusive with html) example: "# Hello World\n\nThis is a test." css: type: string description: Custom CSS styling example: "body { font-family: Arial, sans-serif; margin: 40px; }" javascript: type: string description: JavaScript code (only supported by pagedjs and vivliostyle renderers) example: "document.getElementById('test').innerHTML = 'Dynamic content';" data: type: array description: Array of data objects for template rendering using Nunjucks syntax items: type: object additionalProperties: true example: - name: "John Doe" amount: "1250.00" assets: type: string description: Base64-encoded ZIP file containing assets (images, fonts, etc.) example: "UEsDSYkSE8mCCCF4IHXYab/C+q2RZnG39vKAAAAAElFTkSuQmCC..." options: type: object required: - renderer - sync properties: renderer: type: string enum: - weasyprint - pagedjs - vivliostyle description: PDF rendering engine to use example: "weasyprint" sync: type: string enum: - "true" - "false" description: Whether to render synchronously (returns PDF) or asynchronously (returns pdfid) example: "true" required: - options JobStatusRequest: type: object required: - pdfid properties: pdfid: type: string format: uuid description: PDF job identifier returned from async rendering request example: "5bd48a77-30a8-4d15-bb99-48b55995592c" AsyncJobResponse: type: object required: - pdfid properties: pdfid: type: string format: uuid description: Job identifier to check rendering status example: "5bd48a77-30a8-4d15-bb99-48b55995592c" additionalProperties: false JobStatusResponse: type: object required: - status - message properties: status: type: string description: Current status of the PDF generation job example: "processing" message: type: string description: Human-readable status message example: "PDF is being generated" additionalProperties: false ErrorResponse: type: object properties: message: type: string description: Error message describing what went wrong example: "Required \"html\" Key not found in Body" pdfid: type: string description: PDF ID (only present for invalid pdfid errors) example: "invalid-pdf-id-12345" status: type: string description: Error status (only present for invalid pdfid errors) example: "error" HealthResponse: type: object required: - status - timestamp - services properties: status: type: string enum: - healthy - unhealthy example: "healthy" timestamp: type: string format: date-time example: "2025-10-23T14:34:38.912Z" services: type: object properties: database: type: string enum: - ok - error example: "ok" redis: type: string enum: - ok - error example: "ok" api: type: string enum: - ok - error example: "ok" TrafficStatusResponse: type: object required: - usage - remaining - limit - status - resetDate properties: usage: type: object properties: bytes: type: integer example: 238277 gb: type: integer example: 0 percent: type: integer example: 0 tb: type: integer example: 0 remaining: type: object properties: bytes: type: integer example: 20890720689467 gb: type: integer example: 19456 limit: type: object properties: bytes: type: integer example: 20890720927744 gb: type: integer example: 19456 tb: type: integer example: 20 status: type: string example: "OK" resetDate: type: string format: date example: "2025-11-01" MetricsResponse: type: object required: - counts properties: counts: type: object properties: total: type: integer description: Total PDFs generated all-time example: 23 week: type: integer description: PDFs generated this week example: 23 month: type: integer description: PDFs generated this month example: 12