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.
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 thetitle,textor 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
variablesfield lists every placeholder it uses. - Every placeholder must be supplied. A missing one is rejected with
422 VALIDATION_ERROR, with the names inerror.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:
{"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:
{"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.
{"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. |
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.