Letter templates

Save your branded letter once — body, letterhead, placeholders — then send to anyone by id while Dairo places the address.

A letter template is your branded letter saved once and sent by id: your letterhead, your body copy, your placeholders. To send, you pass the templateId and a recipient, and Dairo renders the letter, fills the placeholders, and places the recipient in the envelope's address window.

Templates use the letters scopes. Reading templates needs letters:read; creating, updating, and previewing them — and sending letters from them — needs letters:send.

How a template renders

Design the template with its recipient address area empty — that is the one rule. Dairo owns the address window: the to address you pass at send time is composited into the window, aligned to the addressPlacement you chose, so one template serves every recipient. A from sender on the send call adds a return-address line at the top of the window.

Inside the HTML, write {{placeholders}} wherever a value changes per letter — a name, an amount, a due date. At render time each placeholder is replaced by the matching templateData value, HTML-escaped so a value can never inject markup. A placeholder with no matching value renders as empty text — preview the template to catch typos before anything is printed.

Fonts

The renderer has no network access, so a template can only use the fonts that ship with it. Refer to them by family name:

FamilyUse it for
FrauncesDisplay type: letterheads, headings. Regular and Medium.
NewsreaderBody text. Regular and Medium. serif and Georgia resolve to it.
Liberation SansSans-serif text. sans-serif, Arial, and Helvetica resolve to it.

Remote font loads are stripped: <link> stylesheets, @import, and @font-face rules that point at a URL never load. Scripts are stripped too.

<div style="font-family:'Fraunces',Georgia,serif; font-size:16pt;">{{senderName}}</div>
<p style="font-family:'Newsreader',Georgia,serif; font-size:10.5pt;">{{body}}</p>

Create a template

POST /v1/letters/templates stores a template. Give it a name and the letter as html (at most 512 KiB; a larger body is a 413). Optionally declare the placeholders in variables (up to 16 KB) as machine-readable documentation for whoever, or whatever agent, fills them later.

Every template returns variables in one shape: a list of { name, type?, example?, label? }. On create and update you may also pass a plain list of names (["firstName"]) or an object of names to types ({ "amountDue": "number" }); Dairo stores and returns the list shape.

curl -X POST https://api.dairo.app/v1/letters/templates \
  -H "Authorization: Bearer $DAIRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Dunning notice",
    "html": "<h1>Payment overdue</h1><p>Dear {{firstName}}, {{amountDue}} is due by {{dueDate}}.</p>",
    "variables": ["firstName", "amountDue", "dueDate"]
  }'

You get back the letter_template with its ltpl_… id — from then on your sending code carries the id, never the document.

{
  "object": "letter_template",
  "id": "ltpl_dunning_notice",
  "name": "Dunning notice",
  "html": "<h1>Payment overdue</h1><p>Dear {{firstName}}, {{amountDue}} is due by {{dueDate}}.</p>",
  "variables": [{ "name": "firstName" }, { "name": "amountDue" }, { "name": "dueDate" }],
  "status": "active",
  "createdAt": "2026-06-22T10:01:02Z",
  "updatedAt": "2026-06-22T10:01:02Z"
}

Preview before you send

POST /v1/letters/templates/{id}/preview renders a proof with a built-in sample recipient — no letter is created and nothing is printed. Pass templateData to fill your placeholders and an optional addressPlacement (left, the default, or right; any other value is a 400). The response carries the composited proof as pdfBase64.

Pass "output": "url" to get a download link instead of the inline PDF. The response then carries pdfUrl (valid for 15 minutes), pageCount, pageSize, and the layout check's valid and summary. Over MCP this is the default; inline: true asks for pdfBase64 instead.

curl -X POST https://api.dairo.app/v1/letters/templates/ltpl_dunning_notice/preview \
  -H "Authorization: Bearer $DAIRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "templateData": { "firstName": "Jane", "amountDue": "CHF 240.00", "dueDate": "2026-07-15" }
  }'
{
  "object": "letter_template_preview",
  "templateId": "ltpl_dunning_notice",
  "addressPlacement": "left",
  "pdfBase64": "JVBERi0xLjQK..."
}

Manage templates

OperationMethod & pathScope
List templatesGET /v1/letters/templatesletters:read
Get one (with its html)GET /v1/letters/templates/{id}letters:read
CreatePOST /v1/letters/templatesletters:send
UpdatePATCH /v1/letters/templates/{id}letters:send
PreviewPOST /v1/letters/templates/{id}/previewletters:send

The list returns templates most recent first and omits each template's html body; fetch one by id for the full document. An update changes any of name, html, variables, or status — set status to archived to retire a template without deleting it, and back to active to restore it.

Send a templated letter

To send one letter from a template, call POST /v1/letters with the templateId as the document source — in place of pdfBase64 — plus the recipient to and the templateData that fills the placeholders. Everything else works exactly like an inline-PDF send: same print and delivery options, same lifecycle, same tracking.

cURL
curl -X POST https://api.dairo.app/v1/letters \
  -H "Authorization: Bearer $DAIRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "templateId": "ltpl_dunning_notice",
    "templateData": { "firstName": "Jane", "amountDue": "CHF 240.00", "dueDate": "2026-07-15" },
    "fileName": "dunning-jane-doe.pdf",
    "to": {
      "name": "Jane Doe",
      "street": "Hauptstrasse", "houseNumber": "12",
      "postalCode": "8001", "city": "Zürich", "country": "CH"
    },
    "delivery": "priority"
  }'

The response is an ordinary letter object at status: "queued", tracked like any other letter.

The template render path is also the only place Dairo can generate a payment slip for you — pass a payment object alongside the templateId. See Print & delivery options.

To send the same template to many recipients, a batch renders it once per recipient — each letter with its own templateData and its own placed address — in a single call.

Templates vs. inline PDFs

Letter templateInline PDF
What you providetemplateId + to + templateDataA finished pdfBase64 or file + to
The addressLeft blank; Dairo places it per recipientAlready positioned in your PDF
Per-recipient copy{{placeholders}} filled from templateDataYou bake a new PDF per recipient
Generated payment slipsSupported (payment object)Bring your own (paymentSlip flag)
Best forRepeated, branded mailOne-off or already-composed documents

Reach for a template whenever the same branded letter goes to more than one recipient — dunning notices, statements, renewal letters. For a single, already-finished document, an inline PDF send is the shorter path.

Next steps

  • Layout & verification — the zones a template must keep clear, ready-made compliant starter templates from GET /v1/letters/requirements, and POST /v1/letters/verify to check a render before it mails.
  • Status & tracking — follow every templated letter from queued to delivered.
  • Pricing — project what a templated run costs before it goes out.

On this page