Filling Word, Excel and PowerPoint templates in n8n
This page answers the question completely, including the two routes that do not involve us. It is written by the people who build DocMint, so the recommendation at the end is not neutral — but the facts are checkable, and where a route is better than ours we say so. Everything here was verified on 29 August 2026.
n8n has no core node for this
Worth stating plainly, because it is the first thing people search for and the answer is short:
n8n ships no built-in node that fills a .docx, .xlsx or
.pptx template from workflow data. The Convert to File and Extract from File nodes
handle CSV, JSON, spreadsheets-as-data and binary conversion; none of them opens a Word template and
replaces placeholders in it. The Google Docs node can do a text replacement inside a Google
document, which is a different thing and only works if your template lives in Google Docs.
So the choice is between a community node, an HTTP call to a rendering service, and running a templating library yourself inside a Code node.
The three routes
| Community node | HTTP Request node | Code node + library | |
|---|---|---|---|
| Setup | Install once, credentials once | None — the node is built in | Self-hosted n8n only |
| Works on n8n Cloud | Yes — verified node | Yes | No |
| Placeholders as real fields | Yes | No — you write the JSON | No |
| Data leaves your network | Yes | Yes | No |
| Cost | Per document | Per document | Free core; paid modules for Excel, slides, images |
Route 1: the community node
n8n-nodes-docmint is on npm — version 0.2.1, published 4 September 2026. It is the official node for this service: we build and run DocMint and we publish the package. It exposes three
resources:
- Document — Fill a template with your data and return the
.docx,.xlsx,.pptx, a PDF, or both; and Inspect, which reports what a template needs without producing anything. - Template — upload, list, get, list versions, roll back, download, delete.
- Account — usage and credits.
The template picker is a searchable list rather than a name you have to remember, and the fill
operation uses n8n's resourceMapper: the template's own placeholders are fetched and
shown as real n8n fields, each one mappable to an expression, instead of a JSON textarea you fill
in blind. There is still a raw-JSON toggle for when a whole object arrives from an earlier node.
Installing it — Cloud and self-hosted
Be careful with claims here, including ours. There are two different install paths and they have different requirements:
Self-hosted n8n: available now. Settings → Community nodes → Install, enter
n8n-nodes-docmint. Or set
N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE=true and install from npm in the usual way.
This works today.
n8n Cloud: available now. n8n published version 0.2.0 in its verified community-node registry on 4 September 2026. In the Nodes panel, open More from the community, find DocMint and install it with one click. n8n permits owners and admins to install verified nodes; members need one of them to do this. Cloud currently serves 0.2.0 while npm has the documentation-only 0.2.1 release; the node code is the same.
Then add a credential: DocMint API, with a key that starts dm_live_. A key is
one API call away and needs no card:
curl -X POST https://docmint.app.mintapis.com/v1/signup \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com","password":"a-long-enough-password"}'
{ "email": "you@example.com",
"api_key": "dm_live_…",
"plan": { "id": "free", "name": "Free", "credits": 30 },
"note": "This is the only time the key is shown. Store it now." }Route 2: a plain HTTP Request node
This needs nothing installed and works on n8n Cloud today. One HTTP Request node, and the binary comes back on the item.
| Setting | Value |
|---|---|
| Method | POST |
| URL | https://docmint.app.mintapis.com/v1/render |
| Authentication | Generic → Header Auth → Authorization: Bearer dm_live_… |
| Send Body | on, JSON |
| Response → Format | File — this is the setting people miss; leave it on JSON and you get bytes as mangled text |
{
"template": "invoice",
"data": {
"invoice_no": "{{ $json.number }}",
"customer": "{{ $json.customer.name }}",
"items": {{ JSON.stringify($json.lines) }}
},
"output": "pdf"
}The document comes back as binary on the item, ready for the Gmail, Google Drive or S3 node that
follows. Ask for "output": "document" for the Office file, "pdf" for a PDF,
or "both" — that is per request, not fixed per template.
Two response headers are worth mapping into your workflow:
x-docmint-credits-remaining, and x-docmint-warnings, which is non-zero when
the render succeeded but something in it deserves a look.
Route 3: a Code node and a library
On self-hosted n8n you can skip the network entirely: allow an external module
(NODE_FUNCTION_ALLOW_EXTERNAL=docxtemplater,pizzip) and fill the template inside a Code
node. If your documents must not leave your network, this is the right answer and no API can beat
it — the data protection argument is settled by the data not moving.
What you take on: docxtemplater's free core covers {tag} replacement, conditions and
loops in Word. Excel templating, PowerPoint slide control, images, HTML and knowing where a tag
failed are separate commercial modules at €500 per module per year, per their pricing page on
29 August 2026. There is also no PDF step — you would need LibreOffice on the n8n host. And the
default for a missing value is to write the literal word undefined into the document,
which is configurable but is what you get if you do not know to change it. The
longer comparison is here.
The thing that saves the most time
Whichever route you take, the loop that actually costs you the afternoon is this: the placeholder names live inside a zipped binary, so you guess the JSON keys, render, open the file in Word, find the field that came out empty, and guess again.
Ask instead. POST /v1/inspect, or the node's Inspect operation, returns a
typed, nested field list with a ready-to-POST skeleton — free, no document, no credit. Live output
from 29 August 2026, abridged:
{ "format": "docx",
"fields": [
{ "name": "invoice_no", "scope": "", "type": "string", "required": true,
"locations": ["word/document.xml, paragraph 1"] },
{ "name": "items", "scope": "", "type": "array", "repeating": true,
"formatters": ["sumProduct", "currency"] },
{ "name": "price", "scope": "items", "type": "number", "required": true } ],
"names": ["invoice_no","customer","description","qty","price","items"],
"sample_data": { … a skeleton you can POST straight back … } }scope is why the node can render a repeating section instead of a textarea:
price lives inside items, and the response says so.
And when the data is wrong anyway, the render fails loudly instead of quietly. Measured live
today, with price missing from a line item:
HTTP 422 — no document, and the credit is refunded
{ "error": {
"code": "placeholder_unresolved",
"message": "The template uses {price|currency} but the data has no \"price\".",
"hint": "Add \"price\" to the data, or write {price|default:} to allow it to be absent.",
"details": { "field": "price",
"location": "word/document.xml, paragraph 2",
"available": ["invoice_no","customer","items","description","qty"] } } }In n8n that arrives as a node error with the message intact, so "Continue on Fail" plus an alert
branch gives you a workflow that never emails a customer a document with a blank total. The refund
is a measurement, not a promise: eight failed renders while this page was written, and
GET /v1/usage reported credits: 0 for all of them.
Which one to pick
- On n8n Cloud, if an owner or admin can install a verified node: the DocMint community node, for searchable templates and field mapping.
- On n8n Cloud where community nodes are disabled: the built-in HTTP Request node.
- On self-hosted n8n, if a person edits the templates: the community node, for the field mapping.
- If the data must not leave your network: the Code node with docxtemplater, and buy the modules you need.
- Above roughly a million documents a year: a flat annual licence beats any per-document meter, including ours.
Where the data comes from, if it arrives as an email. The mapping step assumes you already have fields. When the source is a mailbox — an order confirmation, a delivery note, a supplier invoice — the step in front of DocMint is a parser, not another template engine. MailMint is ours and does that half: an inbound address or an IMAP mailbox in, structured JSON out, with the message’s own SPF, DKIM and DMARC verdict attached. MailMint’s and DocMint’s nodes are both verified and available on n8n Cloud and self-hosted n8n.
Some honest limits before you build on this: DocMint runs on one small instance in Frankfurt with
no SLA and no SOC 2 report, PDF conversion runs one at a time (1,346 ms server-side, measured today,
so bursts queue rather than slow), the free tier is 30 documents a month, and there is no web
dashboard. The full list is on the home page under "What DocMint does not do
yet". Measured the same day: five consecutive .docx renders at 10 ms server-side,
54–74 ms round trip from Germany.