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:
| Family | Use it for |
|---|---|
Fraunces | Display type: letterheads, headings. Regular and Medium. |
Newsreader | Body text. Regular and Medium. serif and Georgia resolve to it. |
Liberation Sans | Sans-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.
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.
You get back the letter_template with its ltpl_… id — from then on your
sending code carries the id, never the document.
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.
Manage templates
| Operation | Method & path | Scope |
|---|---|---|
| List templates | GET /v1/letters/templates | letters:read |
Get one (with its html) | GET /v1/letters/templates/{id} | letters:read |
| Create | POST /v1/letters/templates | letters:send |
| Update | PATCH /v1/letters/templates/{id} | letters:send |
| Preview | POST /v1/letters/templates/{id}/preview | letters: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.
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 template | Inline PDF | |
|---|---|---|
| What you provide | templateId + to + templateData | A finished pdfBase64 or file + to |
| The address | Left blank; Dairo places it per recipient | Already positioned in your PDF |
| Per-recipient copy | {{placeholders}} filled from templateData | You bake a new PDF per recipient |
| Generated payment slips | Supported (payment object) | Bring your own (paymentSlip flag) |
| Best for | Repeated, branded mail | One-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, andPOST /v1/letters/verifyto 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.