# Templates

A template is a reusable letter with `{{placeholders}}`. Save it once, then render one ordinary draft per recipient: a mail merge for invoices, reminders and notices. To send many at once, use [batch sends](/docs/batches.md).

A template holds `text` or explicit `pages`, a `content_type` of `text` or `markdown`, a `style`, `paper` and `envelope`, an optional default `sender`, and an internal `name`. Writing templates needs `letters:write`; reading them needs `letters:read`.

## Placeholder syntax

- Write `{{name}}` anywhere in the `title`, `text` or page text. Spaces inside the braces are allowed: `{{ name }}`.
- Names start with a letter or underscore and may contain letters, digits, `_`, `.` and `-`, up to 64 characters, for example `{{invoice.number}}`.
- The template's `variables` field lists every placeholder it uses.
- Every placeholder must be supplied. A missing one is rejected with `422 VALIDATION_ERROR`, with the names in `error.details.missing`. Extra variables are ignored.
- Values are strings, numbers or booleans, up to 5,000 characters.

### How values are inserted

- Plain-text templates insert values exactly as given.
- Markdown templates escape Markdown punctuation in values, so a value can't add bold text, headings, lists or links. It appears literally.
- HTML is never accepted. A value that looks like an HTML tag is rejected, as HTML is in any Markdown letter.
- Titles are never Markdown.

## Create a template

`POST /templates` with an `Idempotency-Key` header:

```json
{"name": "Invoice reminder", "title": "Invoice {{invoice}}", "content_type": "markdown", "text": "Dear {{customer}},\n\nInvoice **{{invoice}}** for {{amount}} is due on {{due_date}}.\n\nThank you,\nExample Co.", "style": "serif", "paper": "classic", "envelope": "white", "sender": {"name": "Example Co.", "line1": "456 Test Street", "city": "Sample City", "state": "NY", "postal_code": "10001", "country": "US"}, "content_policy_acknowledged": true}
```

The response includes the `template_id` and the `variables` it found:

```json
{"template_id": "template_…", "variables": ["amount", "customer", "due_date", "invoice"], "sender": {"city": "Sample City", "…": "…"}}
```

Default sender addresses are masked in responses.

## Render a draft

`POST /templates/{template_id}/drafts` fills in the variables and creates an ordinary draft. Proof, quote and send it like any other draft; see the [quickstart](/docs/quickstart.md).

```json
{"variables": {"customer": "Sample Recipient", "invoice": "INV-1001", "amount": "$120.00", "due_date": "November 30"}, "recipient": {"name": "Sample Recipient", "line1": "123 Example Avenue", "city": "Exampleville", "state": "CA", "postal_code": "90001", "country": "US"}, "content_policy_acknowledged": true}
```

| Field | Notes |
|---|---|
| `variables` | Required. A value for every placeholder. |
| `recipient` or `recipient_id` | Required. An inline US address, or a confirmed [address reference](/docs/api.md). |
| `sender` or `sender_id` | Optional. Overrides the template's default sender. |
| `title` | Optional. Overrides the rendered title. |

## Manage templates

| Request | Notes |
|---|---|
| `GET /templates` | Lists your templates |
| `GET /templates/{template_id}` | Returns one template |
| `DELETE /templates/{template_id}` | Needs an `Idempotency-Key` header. Drafts and orders made from the template don't change. |

Over MCP, the same operations are the tools `create_template`, `list_templates`, `get_template`, `delete_template` and `create_template_draft`.
