Skip to main content

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 with MARKETPLACE_TRUST=all.
  • npm - install it into your Directus project and restart:
npm install directus-extension-polydoc
directus.example.com

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.

directus.example.com

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.

directus.example.com

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_KEY environment 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 - POST to 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.

directus.example.com

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
directus.example.com

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.

directus.example.com

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 }}.

directus.example.com

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; minimum through extended are 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
}
directus.example.com

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.

directus.example.com

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 an invoices collection (with an invoice JSON 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