> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dairo.app/llms.txt
> Use this file to discover all available pages before exploring further.

# 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.

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

## 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.

## Create a template

`POST /v1/letters/templates` stores a template. Give it a `name` and the
letter as `html`. Optionally declare the placeholder names in `variables` (a
JSON array or object, up to 16 KB) as machine-readable documentation for
whoever — or whatever agent — fills them later.

<CodeGroup>
  ```bash title="cURL" theme={null}
  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"]
    }'
  ```

  ```bash title="CLI" theme={null}
  dairo letter template create \
    --name "Dunning notice" \
    --html '<h1>Payment overdue</h1><p>Dear {{firstName}}, {{amountDue}} is due by {{dueDate}}.</p>' \
    --variables '["firstName", "amountDue", "dueDate"]'
  ```
</CodeGroup>

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

```json theme={null}
{
  "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": ["firstName", "amountDue", "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`). The response carries the composited proof
as `pdfBase64`.

<CodeGroup>
  ```bash title="cURL" theme={null}
  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" }
    }'
  ```

  ```bash title="CLI" theme={null}
  dairo letter template preview ltpl_dunning_notice \
    --data '{"firstName": "Jane", "amountDue": "CHF 240.00", "dueDate": "2026-07-15"}'
  ```
</CodeGroup>

```json theme={null}
{
  "object": "letter_template_preview",
  "templateId": "ltpl_dunning_notice",
  "addressPlacement": "left",
  "pdfBase64": "JVBERi0xLjQK..."
}
```

## Manage templates

| Operation                                                                         | Method & path                             | Scope          |
| --------------------------------------------------------------------------------- | ----------------------------------------- | -------------- |
| [List templates](/api-reference/dairo-api/letters/list-letter-templates)          | `GET /v1/letters/templates`               | `letters:read` |
| [Get one](/api-reference/dairo-api/letters/get-letter-template) (with its `html`) | `GET /v1/letters/templates/{id}`          | `letters:read` |
| [Create](/api-reference/dairo-api/letters/create-letter-template)                 | `POST /v1/letters/templates`              | `letters:send` |
| [Update](/api-reference/dairo-api/letters/update-letter-template)                 | `PATCH /v1/letters/templates/{id}`        | `letters:send` |
| [Preview](/api-reference/dairo-api/letters/preview-letter-template)               | `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.

```bash title="cURL" theme={null}
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": "registered"
  }'
```

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](/letters/print-delivery).

To send the same template to many recipients, a [batch](/letters/batches)
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](/letters/sending-a-letter) is
the shorter path.

## Next steps

* [Layout & verification](/letters/layout-and-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](/letters/status-lifecycle) — follow every templated letter from queued to delivered.
* [Pricing](/letters/pricing) — project what a templated run costs before it goes out.
