PDF Service
Template-based PDF generation — create Jinja2 templates, validate with JSON Schema, generate PDFs.
All endpoints except /health require an API key passed via the X-API-Key header.
X-API-Key: YOUR_API_KEY
curl https://your-domain.com/templates \ -H "X-API-Key: YOUR_API_KEY"
{ "error": "Invalid API key", "message": "Authentication failed" }
- Create a Jinja2 HTML template with a JSON Schema via
POST /templates. - Optionally validate and preview with
POST /validateandPOST /pdf-preview. - Generate a PDF by calling
POST /pdfwith the template ID and data — returns base64-encoded PDF.
Returns a summary list of all templates ordered by creation date (newest first). Does not include the HTML or schema body — use GET /templates/{id} for the full template.
curl https://your-domain.com/templates \ -H "X-API-Key: YOUR_API_KEY"
| Field | Type | Description |
|---|---|---|
id | UUID | Unique template identifier |
name | string | Human-readable template name |
created_at | ISO 8601 | Timestamp when the template was created (UTC) |
[
{
"id": "3c755ab7-bd51-4b6d-8b7c-e344e3d5790a",
"name": "Invoice Template",
"created_at": "2025-03-02T14:27:40.970556Z"
}
]
{ "error": "Invalid API key", "message": "Authentication failed" }
Returns the full template detail including the Jinja2 HTML body and JSON Schema definition. Use this to inspect or retrieve a template before generating a PDF.
| Parameter | Type | Description |
|---|---|---|
id | UUID | The template's unique identifier |
curl https://your-domain.com/templates/3c755ab7-bd51-4b6d-8b7c-e344e3d5790a \ -H "X-API-Key: YOUR_API_KEY"
| Field | Type | Description |
|---|---|---|
id | UUID | Unique template identifier |
name | string | Human-readable template name |
html | string | Jinja2 HTML template body — supports all Jinja2 syntax (variables, loops, conditionals, filters) |
schema | object | JSON Schema (Draft 7) that defines the expected data shape for rendering |
created_at | ISO 8601 | Creation timestamp (UTC) |
updated_at | ISO 8601 | Last update timestamp (UTC) |
{
"id": "3c755ab7-...",
"name": "Invoice Template",
"html": "<html>...</html>",
"schema": { "type": "object", "properties": { ... } },
"created_at": "2025-03-02T14:27:40Z",
"updated_at": "2025-03-02T14:27:40Z"
}
{ "detail": "Template not found" }
Create a new template. Both the Jinja2 HTML and JSON Schema are validated before saving — if either has syntax errors, the request will fail with 422 and a list of errors.
| Field | Type | Description | |
|---|---|---|---|
name | string | required | A descriptive name for the template (e.g. "Kasko Teklif Karsilastirma") |
html | string | required | Jinja2 HTML template body. Supports variables ({{ var }}), loops ({% for %}), conditionals, and filters. Can include external CSS/fonts via CDN links. |
schema | object | required | A valid JSON Schema (Draft 7) defining the data structure expected when rendering. Used for validation — not enforced at render time. |
curl -X POST https://your-domain.com/templates \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Invoice",
"html": "<h1>{{ title }}</h1>",
"schema": { "type": "object", "properties": { "title": { "type": "string" } } }
}'
{
"id": "new-uuid-here",
"name": "Invoice",
"html": "<h1>{{ title }}</h1>",
"schema": { ... },
"created_at": "...",
"updated_at": "..."
}
{ "detail": ["Jinja2 syntax error at line 1: ..."] }
Update an existing template. Only the fields you include in the request body will be changed — omitted fields remain untouched. If html or schema is provided, it will be re-validated before saving.
| Parameter | Type | Description |
|---|---|---|
id | UUID | The template's unique identifier |
| Field | Type | Description | |
|---|---|---|---|
name | string | optional | New template name |
html | string | optional | New Jinja2 HTML template body |
schema | object | optional | New JSON Schema (Draft 7) |
curl -X PUT https://your-domain.com/templates/{id} \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Updated Invoice" }'
{ "id": "...", "name": "Updated Invoice", ... }
{ "detail": "Template not found" }
{ "detail": ["Jinja2 syntax error at line 1: ..."] }
Permanently deletes a template and all its associated assets (images, etc.). This action is irreversible. Returns 204 No Content on success with an empty response body.
| Parameter | Type | Description |
|---|---|---|
id | UUID | The template's unique identifier |
curl -X DELETE https://your-domain.com/templates/{id} \
-H "X-API-Key: YOUR_API_KEY"
(empty response)
{ "detail": "Template not found" }
Validate a Jinja2 HTML template and JSON Schema without persisting anything. Useful for checking syntax before creating or updating a template. If data is provided, the template will also be rendered and the resulting HTML returned in rendered_html.
| Field | Type | Description | |
|---|---|---|---|
html | string | required | Jinja2 HTML template to validate |
schema | object | required | JSON Schema (Draft 7) to validate |
data | object | optional | Sample data to render the template with. If omitted, only syntax validation is performed. |
template_id | UUID | optional | If provided, the template's stored assets (images) will be injected into the render context as base64 data URIs. |
curl -X POST https://your-domain.com/validate \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"html": "<h1>{{ title }}</h1>",
"schema": { "type": "object", "properties": { "title": { "type": "string" } } },
"data": { "title": "Hello" }
}'
| Field | Type | Description |
|---|---|---|
valid | boolean | true if both HTML and schema are syntactically correct |
errors | string[] | List of validation error messages. Empty when valid is true. |
rendered_html | string | null | Rendered HTML output. Only present when data was provided and validation passed. |
{
"valid": true,
"errors": [],
"rendered_html": "<h1>Hello</h1>"
}
{
"valid": false,
"errors": ["Jinja2 syntax error at line 3: unexpected '}'"],
"rendered_html": null
}
Render a saved template with data and return the final HTML output — without generating a PDF. Useful for previewing how the template will look before committing to PDF generation. Template assets (images) are automatically injected as base64 data URIs.
| Field | Type | Description | |
|---|---|---|---|
template_id | UUID | required | ID of the template to render |
data | object | required | Data object matching the template's JSON Schema. All required schema fields must be present. |
curl -X POST https://your-domain.com/pdf-preview \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_id": "3c755ab7-...",
"data": { "title": "Hello" }
}'
| Field | Type | Description |
|---|---|---|
rendered_html | string | The fully rendered HTML string with all variables replaced, loops expanded, and assets injected. |
{ "rendered_html": "<h1>Hello</h1>" }
{ "detail": "Render error: 'title' is undefined" }
{ "detail": "Template not found" }
The main PDF generation endpoint. Renders the template with the provided data, launches a headless Chromium browser to convert the HTML to a PDF (A4 format, with background graphics), and returns the result as a base64-encoded string. Decode the string and save as .pdf to get the file.
| Field | Type | Description | |
|---|---|---|---|
template_id | UUID | required | ID of the template to render |
data | object | required | Data object matching the template's JSON Schema. All required schema fields must be present. |
curl -X POST https://your-domain.com/pdf \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_id": "3c755ab7-...",
"data": { "title": "Hello" }
}'
| Field | Type | Description |
|---|---|---|
pdf_base64 | string | Base64-encoded PDF file content. Decode with standard base64 decoding to get the raw PDF bytes. |
{ "pdf_base64": "JVBERi0xLjQK..." }
{ "detail": "Template not found" }
{ "detail": "PDF generation failed: ..." }
Check service availability and database connectivity. No authentication required. Use this for uptime monitoring or load balancer health checks.
curl https://your-domain.com/health
| Field | Type | Description |
|---|---|---|
status | string | Always "ok" if the service is reachable |
db | string | "ok" if the database connection is healthy, otherwise contains the error message |
{ "status": "ok", "db": "ok" }
{ "status": "ok", "db": "error" }