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

> ## Agent Instructions
> Every Lath operation is POST https://platform.trylath.com/<operation name with dots replaced by slashes>, with a JSON body and `Authorization: Bearer <key>`. `email.send` is POST /email/send.
> Branch on `error.code`, never on `error.message`. Every refusal also carries `error.fix`, which names the next step.
> Send an `Idempotency-Key` header on any operation that is not retry-safe, so a retry cannot run it twice.
> A `lath_test_` key emails only the account's own members and sends no SMS; a `lath_live_` key reaches real recipients and is billed.
> The OpenAPI document, generated from the same registry as the routes, is at https://platform.trylath.com/openapi.json.

# Templates

> Write a message once, in every language you need, and publish it when it is right. A draft cannot send.

<Steps>
  <Step title="A template is a draft until you publish it">
    `email.template.set` saves a **draft** — a subject, HTML, and optionally a plain-text part. Nothing sends from a draft. `email.template.publish` makes that draft the version `email.send` uses from then on, and the version it replaces is kept as history.

    That separation is the whole point of templates existing rather than passing HTML to every send: the copy can be edited, reviewed and previewed without any risk that a half-finished sentence reaches somebody.

    The plain-text part is derived from the HTML when you omit it, so a text alternative always goes out. HTML is capped at 200,000 characters and text at 100,000.

    `layout` decides the frame. `brand`, the default, wraps your HTML in the project's themed frame — the same theme the hosted sign-in pages wear. `none` sends the HTML exactly as written, for when you have designed the whole email yourself.

    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST https://platform.trylath.com/email/template/set \
        -H "Authorization: Bearer $LATH_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "name":"welcome",
          "subject":"Welcome, {{firstName}}",
          "html":"<p>Hello {{firstName}}. Your account is ready.</p>"
        }'

      curl -X POST https://platform.trylath.com/email/template/publish \
        -H "Authorization: Bearer $LATH_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{"name":"welcome"}'
      ```

      ```ts TypeScript theme={null}
      import { createLath } from "@trylath/sdk";

      const lath = createLath({ key: process.env.LATH_API_KEY });

      await lath.email.template.set({
        name: "welcome",
        subject: "Welcome, {{firstName}}",
        html: "<p>Hello {{firstName}}. Your account is ready.</p>",
      });

      await lath.email.template.publish({ name: "welcome" });
      ```

      ```bash CLI theme={null}
      lath email template set \
        --name welcome \
        --subject 'Welcome, {{firstName}}' \
        --html '<p>Hello {{firstName}}. Your account is ready.</p>'

      lath email template publish --name welcome
      ```
    </CodeGroup>
  </Step>

  <Step title="Variables, conditions and loops">
    `{{variable}}` interpolates. `{{#if}}` includes a block when a value is present, and `{{#each}}` repeats one — enough to render an order's lines or greet somebody by name without a second template.

    A syntax error is refused at `email.template.set` **with the line number**, rather than being discovered when a send renders to something strange. The draft is not saved.

    A broadcast supplies each contact's own properties as variables, so the same template personalises itself per recipient without you assembling anything.
  </Step>

  <Step title="Each language is its own variant, versioned on its own">
    Pass `locale` to write a variant — `fr`, `pt-BR`. Each language has its own draft, its own published version and its own history, so translating one does not disturb another and publishing French does not publish a half-finished German.

    Omitting `locale` writes the default variant, which is what a recipient gets when nothing more specific fits them.
  </Step>

  <Step title="Preview before anybody receives it">
    `email.template.preview` renders a template with the variables you give it **exactly as `email.send` would**, brand frame included, and sends nothing.

    It reports any variable the template needs that you did not supply — which is how you find the `{{firstName}}` that renders blank for half your audience, before it does.

    `version: "draft"` previews unpublished changes; the default previews what actually sends today. Pass a `locale` to see what a recipient in that language gets, including which variant the fallback chose for them.

    `email.template.list` shows what exists and `email.template.get` returns one. Some templates are **reserved** — the sign-in and verification messages Lath sends on your behalf. You can rewrite those too, and the same draft-then-publish rule protects them.

    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST https://platform.trylath.com/email/template/preview \
        -H "Authorization: Bearer $LATH_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{"name":"welcome","variables":{"firstName":"Sam"},"version":"draft"}'
      ```

      ```ts TypeScript theme={null}
      import { createLath } from "@trylath/sdk";

      const lath = createLath({ key: process.env.LATH_API_KEY });

      const { result } = await lath.email.template.preview({
        name: "welcome",
        variables: { firstName: "Sam" },
        version: "draft",
      });
      ```

      ```bash CLI theme={null}
      lath email template preview \
        --name welcome \
        --variables '{"firstName":"Sam"}' \
        --version draft
      ```
    </CodeGroup>
  </Step>
</Steps>
