Directus
PolyDoc has a native Directus extension: a single PolyDoc operation you drop into a Flow to convert HTML or URLs to PDF, capture screenshots, and generate EU e-invoices. The result is saved straight into Directus Files, so a later operation can attach it to a record.
Prerequisites
- A PolyDoc account and API key - sign up for free, no credit card required. The free plan includes 150 PDF conversions per month.
- A self-hosted Directus 11 instance. Flows are free on self-hosted Directus, and the PolyDoc operation is a standard (non-sandboxed) extension - so it installs on self-hosted Directus, not Directus Cloud.
Install the PolyDoc extension
The PolyDoc extension adds a single PolyDoc operation to Directus Flows. It is a standard (non-sandboxed) API extension, so it installs on self-hosted Directus in one of two ways:
- Marketplace - open Settings → Marketplace, search for
directus-extension-polydoc, and install. The Marketplace lists non-sandboxed extensions only when your instance runs withMARKETPLACE_TRUST=all. - npm - install it into your Directus project and restart:
npm install directus-extension-polydoc
Use Case 1: PDF from a saved template
Render a saved PolyDoc template to a branded PDF and store it in Directus Files. This is the simplest Flow: one PolyDoc operation, run on demand or from any trigger.Manual trigger → PolyDoc (PDF) → file saved to Directus Files
Add the PolyDoc operation
In Directus, open Settings → Flows and click Create Flow. Give it a name (e.g. Invoice PDF) and pick a trigger. A Manual trigger is fine to start, but note it only fires from the Content module on a bound collection - for a quick standalone test pick Webhook instead (see the last step). On the Flow canvas, click + to add an operation and choose PolyDoc from the list.
Give the operation a Key (e.g. polydoc_pdf) - later steps reference its result by that key.
Choose the source and template
In the PolyDoc operation, set:
- Operation: HTML/URL to PDF
- Source: Template (saved PolyDoc template)
- Template ID: your template's short ID from the Dashboard (see Templates)
- Template Data: the data your template renders, for example:
{
"invoice_number": "INV-001",
"invoice_date": "2026-01-31",
"customer_name": "Acme Group",
"items": [
{ "description": "Consulting", "quantity": 3, "price": 120 }
]
}
Bind values to earlier steps or the trigger with {{ ... }} when the Flow has a data source. The PDF layout options below (Page Format, Landscape, Print Background, margins, Page Ranges, accessible Tagged PDF) default to A4 portrait; adjust as needed.
Save the PDF to Directus Files
Set how the file comes back:
- Delivery: Save to Directus File (the default)
- Target Folder: an optional Directus Files folder
- Filename: e.g.
invoice.pdf
On success the operation returns this into the Flow data chain:
{
"fileId": "a1b2c3d4-...",
"filename": "invoice.pdf",
"contentType": "application/pdf",
"sizeBytes": 51234
}
fileId is the UUID of a real file in Directus Files. Any later operation can use {{ polydoc_pdf.fileId }} to attach it to a record, email it, or expose it through the API.
Add your API key and run
Set the connection, then run:
- API Key: paste a key from the Dashboard, or leave it blank to read the
POLYDOC_API_KEYenvironment variable (recommended - keeps the key out of the Flow definition) - Sandbox: turn on to test against sandbox quota (watermarked output)
Save the Flow, then trigger it. Directus has no run button in the Flow editor, so how you fire it depends on the trigger you picked:
- Manual: bind the trigger to a Collection in its settings, then open the Content module, select an item in that collection, and click the flow button in the toolbar (or the item's sidebar).
- Webhook: Directus gives you a URL -
POSTto it (e.g.curl -X POST <url>) to fire the Flow. Easiest for this use case, since the PDF needs no input record.
Then open Settings → Files (or the Flow's Logs) - the rendered PDF is now a file in Directus.
Use Case 2: Screenshot a URL
Capture a screenshot of any URL and save the image to Directus Files - handy for archiving a page, generating social cards, or snapshotting a dashboard on a schedule.Trigger → PolyDoc (Screenshot) → image saved to Directus Files
Add and configure the operation
Add a PolyDoc operation to a Flow (Key: polydoc_screenshot) and set:
- Operation: Capture Screenshot
- Source: URL (render a web page)
- URL:
https://example.com - Image Type: PNG, JPEG, or WebP
- Full Page: on to capture the whole scrollable page
- Viewport Width / Height and Device Pixel Ratio (e.g. 2 for retina) control the capture size
Save the image and run
Leave Delivery on Save to Directus File, set a Filename (e.g. example.png), add your API Key (or the POLYDOC_API_KEY env var), and run the Flow.
The operation returns {{ polydoc_screenshot.fileId }} - the new image in Directus Files.
Use Case 3: E-invoice from a record
Turn a new invoice record into a compliant EU e-invoice - a Factur-X / ZUGFeRD hybrid PDF/A-3 that carries machine-readable EN 16931 XML inside the PDF - and attach it back to the record.Event Hook (items.create) → PolyDoc (E-Invoice) → Update Data (attach file)
Create the invoices collection
Create the collection the invoices live in. In Settings → Data Model, add a collection named invoices with two load-bearing fields:
invoice- a JSON field holding the structured invoice (the object that becomes the embedded EN 16931 XML).einvoice_file- a File field that receives the generated PDF.
The Flow fires on records in this collection, reads the invoice from invoice, and writes the finished PDF back to einvoice_file. Add whatever other columns you need (customer, status, and so on); only these two are wired into the Flow.
Trigger on new invoice records
Create a Flow with an Event Hook trigger so it fires when an invoice is created:
- Type: Action (Non-Blocking)
- Scope:
items.create - Collections:
invoices
The new record is available to the operations that follow as {{ $trigger.payload }}.
Configure the E-Invoice operation
Add a PolyDoc operation (Key: polydoc_einvoice) and set:
- Operation: Generate E-Invoice
- E-Invoice Standard: ZUGFeRD or Factur-X
- E-Invoice Profile:
en16931(the standard EN 16931 profile;minimumthroughextendedare also available) - Verify Compliance: on - fails the operation if the result is not a valid PDF/A-3 e-invoice
- Source: Template (the branded invoice layout, as in Use Case 1) or inline HTML - this is the human-readable page
- Invoice Data: the structured invoice that becomes the embedded XML
Invoice Data takes a structured object. Bind it to the record's invoice field with {{ $trigger.payload.invoice }}, or write the values out inline:
{
"number": "INV-001",
"issueDate": "2026-01-31",
"dueDate": "2026-03-02",
"currencyCode": "EUR",
"seller": {
"name": "Your Company GmbH",
"address": { "line1": "Main St 1", "city": "Berlin", "postalCode": "10115", "countryCode": "DE" },
"taxId": "DE123456789"
},
"buyer": {
"name": "Customer SARL",
"address": { "line1": "Rue 2", "city": "Paris", "postalCode": "75001", "countryCode": "FR" }
},
"lines": [
{ "description": "Widget", "quantity": 2, "unitPrice": 10, "lineTotal": 20, "vatRate": 19, "vatCategoryCode": "S" }
],
"taxSummary": [{ "categoryCode": "S", "rate": 19, "taxableAmount": 20, "taxAmount": 3.8 }],
"paymentTerms": "Net 30",
"totalNetAmount": 20,
"totalTaxAmount": 3.8,
"totalGrossAmount": 23.8
}
Attach the PDF to the record
Add an Update Data operation to attach the generated file to the invoice record:
- Collection:
invoices - IDs:
{{ $trigger.key }} - Payload:
{
"einvoice_file": "{{ polydoc_einvoice.fileId }}"
}
einvoice_file is a File field on the invoices collection. Toggle the Flow active, create an invoice, and the compliant PDF lands in Directus Files and on the record.
Load the example Flows
The extension repo ships three ready-to-load Flow definitions, one per use case above:
pdf-from-template.flow.json- render a saved template to a PDF.url-screenshot.flow.json- screenshot a URL and store the PNG.einvoice-from-record.flow.json- turn a new invoice record into a ZUGFeRD / Factur-X PDF. Fires on aninvoicescollection (with aninvoiceJSON field), so create that first - see Use Case 3.
Directus has no one-click Flow import, so the repo includes a zero-dependency loader. Point it at your instance with an admin static token and it creates the Flow and wires the operation for you:
git clone https://github.com/polydoc-tech/directus-extension-polydoc
cd directus-extension-polydoc
DIRECTUS_URL=https://directus.example.com \
DIRECTUS_TOKEN=<admin static token> \
node examples/import.mjs pdf-from-template.flow.json
It prints the new Flow's admin URL. Open it, set your API key (or the POLYDOC_API_KEY env var), and run. The loader creates the Flow and its operation only, not any collections: the PDF and screenshot examples run as-is, while the e-invoice example needs the invoices collection from Use Case 3.
Next steps
- New to PolyDoc? Create a free account - 150 conversions per month, no credit card.
- Compare options: see how PolyDoc compares to other HTML-to-PDF APIs.
- EU e-invoicing: PolyDoc also generates Factur-X and ZUGFeRD e-invoices from JSON.