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

# Render a template

> POST /v1/templates/{id}/render — render a saved template with data and inspect the resulting subject, html, and text.

Resolve a saved template's merge variables against a data object and return the final subject, HTML, and text — without sending anything. Useful for previews and QA.

**`POST /v1/templates/{id}/render`**

This is a pure render: nothing is queued or delivered. To send a template, pass `templateId` + `data` to [POST /v1/emails](/api-reference/emails/send) instead — the pipeline renders it for you.

## Path parameters

<ParamField body="id" type="string" required>
  The template `id` or `slug` to render.
</ParamField>

## Body parameters

<ParamField body="data" type="object">
  Merge variables, keyed by placeholder name. Nested objects are reachable with dot paths (`{{user.name}}`). Omit to render with no substitutions.
</ParamField>

## Request

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.drin.run/v1/templates/order-receipt/render \
    -H "Authorization: Bearer $DRIN_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "data": { "firstName": "Sam", "orderId": "A-1042" }
    }'
  ```

  ```typescript Node.js theme={null}
  import { DrinClient } from "@drin00/sdk";

  const drin = new DrinClient({ apiKey: process.env.DRIN_API_KEY });

  const rendered = await drin.templates.render("order-receipt", {
    firstName: "Sam",
    orderId: "A-1042",
  });

  if (rendered.missing.length) {
    console.warn("Unfilled variables:", rendered.missing);
  }
  ```
</CodeGroup>

## Response

<ResponseField name="subject" type="string">
  The rendered subject line.
</ResponseField>

<ResponseField name="html" type="string | null">
  The rendered HTML body, or `null` if the template has none.
</ResponseField>

<ResponseField name="text" type="string | null">
  The rendered plain-text body, or `null`.
</ResponseField>

<ResponseField name="missing" type="string[]">
  Variables referenced by the template but absent from `data`. They render as empty strings; surface this array in QA to catch gaps.
</ResponseField>

```json 200 OK theme={null}
{
  "subject": "Receipt A-1042",
  "html": "<p>Hi Sam, thanks for your order.</p>",
  "text": null,
  "missing": []
}
```

<Tip>
  **Previewing an unsaved draft.** To render a template you haven't saved yet — e.g. a live editor — use [POST /v1/templates/preview](/api-reference/templates/preview), which takes the draft fields inline instead of an id.
</Tip>
