Sandboxed by default
Each render runs in an isolated subprocess with a 15 s wall-clock kill, fresh tempdir, no network, and a Jinja SandboxedEnvironment. Untrusted payloads stay untrusted.
Upload a Word, Excel, PowerPoint, or PDF template once. POST a JSON payload to /v1/render — instadoc fills the placeholders and streams back the finished document. No more hand-rolled docx-templater.
{ "client": "Hover Logistics BV", "invoice_no": "INV-2026-0421", "amount": € 1,820.00, "due_date": "2026-06-15"}Invoice
INV-2026-0421
Atelier
Studio
Live counters
Updated every five minutes. Coarse aggregates only — nothing about individual users, templates, or payloads is ever exposed.
01 / How it works
The flow is deliberately boring — one upload, one POST, one download. The hard parts (sandboxing, MIME validation, render timeouts, signed storage) live on our side.
A Word, Excel, PowerPoint, or PDF file with {{ placeholder }} syntax inside. Brand fonts, tables, images, conditional rows — all preserved.
Reference the template by id, hand us your data. We sandbox the Jinja environment so untrusted payloads can’t escape the renderer.
The rendered file comes straight back in the response body. No webhook dance. No polling. 200 OK · binary.
02 / What you get
docx-templater on its own is a starting line, not a finish. We did the unglamorous parts so you can ship the feature, not the infrastructure.
Each render runs in an isolated subprocess with a 15 s wall-clock kill, fresh tempdir, no network, and a Jinja SandboxedEnvironment. Untrusted payloads stay untrusted.
Sub-second median end-to-end for docx / xlsx / pptx. PDF goes through a warmed LibreOffice pool and lands well under two seconds.
Stitch multiple templates into one document with ordered, conditional blocks. JSONPath-driven block context, per-block overrides, hard caps so no single render runs away.
Upload a .potx master once. Every template in a composition inherits its slide masters, fonts, and colour palette — enforced via signature hash on upload.
argon2id at rest. Full key body returned once at issue. Per-key rate limits, audit log on every render, prefix-only in our logs.
Every upload is a new immutable version. Roll forward or pin a render to a specific version — your templates change, your old documents don’t.
Hosted in Amsterdam by default. Every privileged action lands in an append-only audit log. SOC 2 controls implemented; DPA on request.
OpenAPI 3 spec. Strict JSON schemas. Predictable error codes (402 for plan limits, 423 for locked, 401 for rotated keys). No surprise behaviour.
03 / Render in 12 lines
Pick your language. Copy the snippet. Swap in your API key and a template id. That’s the integration.
curl -X POST https://api.instadoc.dev/v1/render?format=pdf \-H "Authorization: Bearer $INSTADOC_API_KEY" \-H "Content-Type: application/json" \-d '{"template_id": "tpl_invoice_v3","client": "Hover Logistics BV","invoice_no": "INV-2026-0421","amount": 1820.00,"due_date": "2026-06-15"}' --output invoice.pdf
04 / Pricing
Start on Starter. Move to Growth when production calls. Scale when you stop counting renders.
05 / FAQ
If we missed yours, email us. Replies come from a person.
.docx), Excel (.xlsx), PowerPoint (.pptx), and PDF (via a sandboxed LibreOffice pipeline). Upload a template once, define placeholders with familiar Jinja-style syntax, and render at scale..potx master) so every slide deck inherits the same brand. Hard limits: 50 blocks per composition, 200 slides or pages per render.Authorization: Bearer …. Keys are hashed with argon2id; the full key body is shown to you exactly once at creation and never logged.Ready when you are
Spin up a free API key in under a minute. Render your first document on the same coffee.