Templates / Letter
Letter
DIN 5008 style business letter: sender line, address window, reference block, subject and body paragraphs from JSON. The template that makes generated correspondence look like it came from a person.
1 page, A4. Rendered in 25 ms. 13 inputs, all optional.
Inputs
Everything variable comes in through sys.inputs. Missing keys fall back to sensible defaults, so an agent can send only what it knows.
| Key | Sample value |
|---|---|
closing | Kind regards, |
date | 28 September 2026 |
enclosures | Quote Q-2026-118 |
logo | logo.png |
paragraphs | JSON, 430 chars |
recipient | JSON, 71 chars |
reference | Q-2026-118 |
salutation | Dear Ms Hartmann, |
sender | Meridian Studio GmbH |
sender_line | Meridian Studio GmbH · Rosenthaler Str. 41 · 10178 Berlin |
signer | Mara Ehrlich |
signer_role | Managing Director |
subject | Your quote for the customer portal redesign |
Render it
After copying the template into your account:
curl -X POST https://api.foliant.dev/v1/render \
-H "Authorization: Bearer $FOLIANT_API_KEY" \
-H "Content-Type: application/json" \
-o letter.pdf -d @- <<'JSON'
{ "template": "letter.typ",
"inputs": {
"closing": "Kind regards,",
"date": "28 September 2026",
"enclosures": "Quote Q-2026-118",
"logo": "logo.png",
"paragraphs": "[\"Thank you for the good conversation on Tuesday. Attached you will find our quote for the redesign of your customer portal, valid until 26 October.\",\"We suggest starting with the two-day discovery workshop in the week of 13 October so the design phase can begin in November. If that timing works for your team, a short confirmation is all we need.\",\"I am happy to walk you through the positions in a call whenever it suits you.\"]",
"recipient": "[\"Northwind Traders\",\"Lena Hartmann\",\"Kastanienallee 7\",\"10435 Berlin\"]",
"reference": "Q-2026-118",
"salutation": "Dear Ms Hartmann,",
"sender": "Meridian Studio GmbH",
"sender_line": "Meridian Studio GmbH · Rosenthaler Str. 41 · 10178 Berlin",
"signer": "Mara Ehrlich",
"signer_role": "Managing Director",
"subject": "Your quote for the customer portal redesign"
} }
JSON
Through MCP, render_document with template: "letter.typ" and the same inputs; get_template or fetch lists the keys.
Source
template.typ, 26 lines
#let input(k, default: "") = sys.inputs.at(k, default: default)
#let recipient = json(bytes(input("recipient", default: "[]")))
#let paragraphs = json(bytes(input("paragraphs", default: "[]")))
#let logo = input("logo")
#set page(paper: "a4", margin: (top: 20mm, bottom: 20mm, left: 25mm, right: 20mm))
#set text(font: "Libertinus Serif", size: 11pt, fill: rgb("1a1917"))
#set par(justify: false, leading: 0.7em)
#align(right)[#if logo != "" { image(logo, width: 36mm) } else { text(size: 14pt, weight: 600)[#input("sender")] }]
#v(12mm)
#text(size: 7.5pt, fill: luma(110))[#input("sender_line")]
#v(2mm)
#block(height: 30mm)[#for l in recipient [#l \ ]]
#v(4mm)
#grid(columns: (1fr, auto), [#text(size: 9pt, fill: luma(110))[Reference: #input("reference")]], [#input("date")])
#v(10mm)
#text(weight: 600)[#input("subject")]
#v(5mm)
#input("salutation")
#v(3mm)
#for p in paragraphs [#p #v(3mm)]
#v(2mm)
#input("closing")
#v(14mm)
#input("signer") \ #text(size: 9.5pt, fill: luma(110))[#input("signer_role")]
#if input("enclosures") != "" [#v(8mm) #text(size: 9pt, fill: luma(110))[Enclosure: #input("enclosures")]]