---
title: "Message templates"
description: "Create, publish, archive, look up, page, and preview reusable SMS and email message templates."
canonical: "https://studio.inttegro.com/api/message-templates"
format: inttegro-machine-docs/v1
language: "Ruby"
sdk_version: "v10.0.0"
reader_profile: optional
reader_manifest: "https://studio.inttegro.com/machine/ruby/readers/index.json"
reader_identification: "Optional: declare your client only if known and your current-session capabilities; use reader_manifest for supplemental recommendations."
preamble_estimated_tokens: 710
model_token_report: "https://studio.inttegro.com/machine/token-report.json"
preamble_questions: 5
preamble_source: "machine-only-decisions"
recommended_mcp_tools: ["get_message_template","preview_message_template","send_customer_template"]
estimated_tokens: 7182
token_estimate_method: "utf8_bytes_divided_by_4"
---

## Machine preamble

**Summary:** Create, publish, archive, look up, page, and preview reusable SMS and email message templates. This Ruby representation uses the selected SDK's native names wherever Studio has a verified mapping.

### Five questions

#### Q1. Is Message templates the right source for this task?

Use this reference for create, publish, archive, look up, page, and preview reusable sms and email message templates. For the complete outcome or lifecycle, start with [Chimes product guide](https://studio.inttegro.com/machine/ruby/products/chimes.md); return here for exact operations and fields.

#### Q2. What is the first decision rule for keep draft editing separate from live message delivery?

A template owns exactly one channel. Choose SMS or email at creation and do
not combine their content fields or attempt to change the channel later.

#### Q3. What is the second decision rule for keep draft editing separate from live message delivery?

Chime sends use the published version. Updating a template changes its draft;
publish that draft before expecting new sends, schedules, or broadcasts to
use it. Inspect the unpublished-changes flag when deciding whether publication
is required.

#### Q4. What is the third decision rule for keep draft editing separate from live message delivery?

Render a preview with representative variables before publishing. Every
reference must be declared, input must match the variable contract, and the
rendered result must satisfy the selected transport's safety and size rules.

#### Q5. What is the fourth decision rule for keep draft editing separate from live message delivery?

Archiving is terminal for new use and has no unarchive operation. Historical
records remain readable, but new delivery needs an active replacement.

### Recommended MCP assistance

Use these through an authenticated Inttegro MCP connection. This document remains the contract source.

- [`get_message_template`](https://studio.inttegro.com/machine/ruby/inttegro-mcp/tools.md#get_message_template) — read; no mutation confirmation. Gets one template with editable channel content and version state while withholding variable defaults and private email-header values.
- [`preview_message_template`](https://studio.inttegro.com/machine/ruby/inttegro-mcp/tools.md#preview_message_template) — read; no mutation confirmation. Renders the current draft with supplied non-secret variables so the merchant can review the actual SMS or email before publishing.
- [`send_customer_template`](https://studio.inttegro.com/machine/ruby/inttegro-mcp/tools.md#send_customer_template) — action; exact user confirmation required. Renders and validates a published template, shows the actual customer-facing copy for confirmation, and sends it once to a saved customer by explicit SMS or email transport.…

## Document content

# Message templates

Use this reference for exact request attributes, response envelopes, object shape, and examples. For customer-notification patterns and when to use templates with Chimes, start with the [Chimes product guide](https://studio.inttegro.com/machine/ruby/products/chimes.md).

## Keep draft editing separate from live message delivery

The four decision rules are in the machine preamble above.

## The message template object

A Message Template stores one channel of content. SMS templates use

[`message_template.sms.message_template`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html); email templates use
[`message_template.email.subject`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) and
[`message_template.email.html`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html). Do not mix SMS and email
content in the same template.

### Properties

- [`about`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `string`

  Optional description of the template's purpose. Omitted when no description
  is set.

- [`archived_at`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `timestamp`

  When the template was archived. Omitted for active templates. Archived
  templates cannot be updated, published, rendered, or used for new Chimes.

- [`attachments`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `array`

  Up to 25 email attachment file IDs. Every entry must be nonempty and match
  `file_` followed by alphanumeric characters. Attachments
  are accepted only for email templates. Previews return the attachment IDs,
  but Chime requests currently reject stored templates that contain
  attachments. Omitted when the template has no attachments.

- [`channel`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `enum`

  Template channel: [`Inttegro::MessageTemplate::Channel::SMS`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/Channel.html#SMS-constant) or
  [`Inttegro::MessageTemplate::Channel::EMAIL`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/Channel.html#EMAIL-constant).

- [`created_at`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `timestamp`

  When the template was created.

- [`draft_version`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `integer`

  Current draft version. The first edit after publication advances this
  number; later edits replace that same draft until it is published.

- [`email`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html)

  Email template content. Present when message\_template.channel is "email" .

  - [`email.from`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `object`

    Optional sender mailbox template. Omitted when unset.

  - [`email.headers`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `object`

    Optional custom header templates. Delivery, routing, and authentication headers cannot be overridden.

  - [`email.html`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `string`

    HTML template body. Required for email templates.

  - [`email.reply_to`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `object`

    Optional reply-to mailbox template. Omitted when unset.

  - [`email.subject`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `string`

    Email subject template. Required for email templates.

- [`has_unpublished_changes`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `boolean`

  `true` when the draft differs from the published version.

- [`id`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `string`

  Generated template ID. The API assigns this value; clients must not provide
  `id`, `template_id`, or a custom key on
  create.

- [`locale`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `string`

  Locale for the template. Defaults to `'en'` when omitted.

- [`name`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `string`

  Human-readable template name.

- [`published_at`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `timestamp`

  When the current published version was published. Omitted until the first
  publication.

- [`published_version`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `integer`

  Version number currently used by Chime sends. Omitted until the template is
  published.

- [`purpose`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `string`

  Template category, such as `'receipt'`,
  `'shipping_update'`, `'marketing'`, or
  `'reminder'`. The API trims and stores this value in
  lowercase.

- [`sms`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html)

  SMS template content. Present when message\_template.channel is "sms" .

  - [`sms.message_template`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `string`

    SMS body template. Required for SMS templates.

- [`status`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `enum`

  Current lifecycle state:
  [`Inttegro::MessageTemplate::Status::DRAFT`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/Status.html#DRAFT-constant),
  [`Inttegro::MessageTemplate::Status::PUBLISHED`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/Status.html#PUBLISHED-constant), or
  [`Inttegro::MessageTemplate::Status::ARCHIVED`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/Status.html#ARCHIVED-constant).

- [`updated_at`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `timestamp`

  When the template was last changed.

- [`variables`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html)

  Variable declarations available inside template content. Omitted when none are declared.

  - [`variables.about`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `string`

    Optional description shown to operators.

  - [`variables.default`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `any`

    Default value used when an optional variable is omitted.

  - [`variables.items`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `array`

    Nested item fields for array variables. Nested arrays are not supported.

  - [`variables.name`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `string`

    Variable name. Must start with a lowercase letter and contain lowercase letters, numbers, or underscores.

  - [`variables.required`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `boolean`

    Whether callers must provide this variable when rendering.

  - [`variables.type`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `enum`

    [`Inttegro::MessageTemplate::VariableType::ARRAY`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/VariableType.html#ARRAY-constant), [`Inttegro::MessageTemplate::VariableType::BOOLEAN`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/VariableType.html#BOOLEAN-constant), [`Inttegro::MessageTemplate::VariableType::DATE`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/VariableType.html#DATE-constant), [`Inttegro::MessageTemplate::VariableType::DATETIME`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/VariableType.html#DATETIME-constant), [`Inttegro::MessageTemplate::VariableType::EMAIL`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/VariableType.html#EMAIL-constant), [`Inttegro::MessageTemplate::VariableType::INTEGER`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/VariableType.html#INTEGER-constant), [`Inttegro::MessageTemplate::VariableType::NUMBER`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/VariableType.html#NUMBER-constant), [`Inttegro::MessageTemplate::VariableType::PHONE`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/VariableType.html#PHONE-constant), [`Inttegro::MessageTemplate::VariableType::STRING`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/VariableType.html#STRING-constant), or [`Inttegro::MessageTemplate::VariableType::URL`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/VariableType.html#URL-constant).

- [`version`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) — `integer`

  Current template version number.

Template expressions use `'{{variable_name}}'` for values,

`'{{#if variable}}...{{else}}...{{/if}}'` for conditional
text, and `'{{#each items as item}}...{{/each}}'` for arrays.

### Design templates that render safely

Every reference must match a declared variable. Rendering rejects unknown input
fields, missing required values, invalid value types, and arrays with undeclared
item fields. `date` values use

`YYYY-MM-DD`; `datetime` values use RFC 3339;
URL variables must be absolute HTTP or HTTPS URLs without embedded user
credentials.

SMS output can contain at most 120 Unicode characters after variables are
substituted. Email variables are escaped when inserted into HTML, while subjects,
mailboxes, and custom header values reject line breaks and unsafe control
characters. Email HTML accepts common message-layout elements but rejects scripts,
event handlers, and unsafe link or image schemes. A preview succeeds only when the
rendered email contains readable text and passes content safety checks.

## Create a message template

Create a reusable SMS or email template. The new template starts as
[`Inttegro::MessageTemplate::Status::DRAFT`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/Status.html#DRAFT-constant); publish it before using it in Chime sends, schedules, or broadcasts.

### Request body

- `about` — `string` — wire-only

  Optional description shown alongside the template.

- `attachments` — `array` — wire-only

  Up to 25 email attachment file IDs. Only allowed when
  `channel` is
  [`Inttegro::MessageTemplate::Channel::EMAIL`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/Channel.html#EMAIL-constant).
  Every entry must be nonempty and match `file_` followed
  by alphanumeric characters, such as `file_ABC123`.

- `channel` — `enum` — required — wire-only

  [`Inttegro::MessageTemplate::Channel::SMS`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/Channel.html#SMS-constant) or
  [`Inttegro::MessageTemplate::Channel::EMAIL`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/Channel.html#EMAIL-constant).

- `email` — `object` — wire-only

  Required when `channel` is
  [`Inttegro::MessageTemplate::Channel::EMAIL`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/Channel.html#EMAIL-constant).
  Must include `email.subject` and
  `email.html`; may include
  `email.from`, `email.reply_to`, and
  `email.headers`.

- `locale` — `string` — wire-only

  Optional locale. Defaults to `'en'`.

- `name` — `string` — required — wire-only

  Human-readable template name.

- `purpose` — `string` — required — wire-only

  Template category for filtering. The API trims and stores it in
  lowercase.

- `sms` — `object` — wire-only

  Required when `channel` is
  [`Inttegro::MessageTemplate::Channel::SMS`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/Channel.html#SMS-constant).
  Must include `sms.message_template`.

- `variables` — `array` — wire-only

  Variable declarations used by the SMS body, email subject, HTML, sender, reply-to, and headers.

### Response

Returns a top-level [`message_template`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) object. Store
[`message_template.id`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html); it is the value Chime requests
use as `message_template.template_id`.

**Request — POST /message\_templates/create**

```ruby
require "inttegro"

client = Inttegro::Client.new(api_key: ENV.fetch("INTTEGRO_API_KEY"))
result = client.message_templates.create(
  name: "Shipping update SMS",
  channel: "sms",
  purpose: "shipping_update",
  variables: [
    {
      name: "customer_name",
      type: "string",
      required: true,
    },
    {
      name: "tracking_url",
      type: "url",
      required: true,
    },
  ],
  sms: {
    message_template: "Hi {{customer_name}}, your order shipped. Track it: {{tracking_url}}",
  },
  idempotency_key: "mtpl-create-shipping-sms-001"
)
```

**Response**

```json
{
  "message_template": {
    "id": "mtpl_WkPvqTrqGsopu07wfC7ttoWqmfwt48ZW7BGvYU",
    "name": "Shipping update SMS",
    "channel": "sms",
    "purpose": "shipping_update",
    "locale": "en",
    "status": "draft",
    "version": 1,
    "draft_version": 1,
    "has_unpublished_changes": true,
    "variables": [
      { "name": "customer_name", "type": "string", "required": true },
      { "name": "tracking_url", "type": "url", "required": true }
    ],
    "sms": {
      "message_template": "Hi {{customer_name}}, your order shipped. Track it: {{tracking_url}}"
    },
    "created_at": "2026-06-22T10:30:00Z",
    "updated_at": "2026-06-22T10:30:00Z"
  }
}
```

## Update a message template

Update mutable fields by replacing the current draft. The first edit after publication advances the draft version; later edits keep that same draft version until it is published. The published version remains stable until you publish the draft.

### Request body

- `about` — `string` — wire-only

  Optional replacement description.

- `attachments` — `array` — wire-only

  Up to 25 replacement email attachment file IDs. Only allowed for email
  templates. Every entry must be nonempty and match
  `file_` followed by alphanumeric characters, such as
  `file_ABC123`. Send an empty array to clear the
  attachments.

- `channel` — `enum` — wire-only

  Optional channel assertion. Existing templates cannot move between
  [`Inttegro::MessageTemplate::Channel::SMS`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/Channel.html#SMS-constant) and
  [`Inttegro::MessageTemplate::Channel::EMAIL`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/Channel.html#EMAIL-constant); create a new
  template for a different channel.

- `email` — `object` — wire-only

  Complete replacement email content. When supplied, it must include both
  `email.subject` and `email.html`;
  nested email fields are not patched individually.

- `id` — `string` — required — wire-only

  Template ID to update.

- `locale` — `string` — wire-only

  Replacement locale.

- `name` — `string` — wire-only

  Replacement name.

- `purpose` — `string` — wire-only

  Replacement purpose.

- `sms` — `object` — wire-only

  Complete replacement SMS content. When supplied, it must include
  `sms.message_template`.

- `variables` — `array` — wire-only

  Replacement variable declarations. Send an empty array to remove every
  declaration.

### Response

Returns the updated [`message_template`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) with
[`message_template.has_unpublished_changes`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) set to
`true`.  An empty `about` clears that field.

**Request — POST /message\_templates/update**

```ruby
require "inttegro"

client = Inttegro::Client.new(api_key: ENV.fetch("INTTEGRO_API_KEY"))
result = client.message_templates.update(
  id: "mtpl_WkPvqTrqGsopu07wfC7ttoWqmfwt48ZW7BGvYU",
  sms: {
    message_template: "Hi {{customer_name}}, your order shipped. Track: {{tracking_url}}",
  },
  idempotency_key: "mtpl-update-shipping-sms-001"
)
```

## Publish a message template

Publish the current draft version. Chime sends, schedules, and broadcasts render only the published version.

### Request body

- `id` — `string` — required — wire-only

  Template ID to publish.

### Response

Returns the published [`message_template`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) with
[`message_template.status`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) set to [`Inttegro::MessageTemplate::Status::PUBLISHED`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/Status.html#PUBLISHED-constant)  and [`message_template.has_unpublished_changes`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html) set to
`false`.

**Request — POST /message\_templates/publish**

```ruby
require "inttegro"

client = Inttegro::Client.new(api_key: ENV.fetch("INTTEGRO_API_KEY"))
result = client.message_templates.publish(
  template_id: "mtpl_WkPvqTrqGsopu07wfC7ttoWqmfwt48ZW7BGvYU",
  idempotency_key: "mtpl-publish-shipping-sms-001"
)
```

## Archive a message template

Archive a template so it cannot be updated, published, rendered, or used for new Chime sends. Archiving preserves the historical record and existing Chimes. Lookup and page requests continue to return the archived record; there is no unarchive operation.

### Request body

- `id` — `string` — required — wire-only

  Template ID to archive.

### Response

Returns the archived [`message_template`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html).

**Request — POST /message\_templates/archive**

```ruby
require "inttegro"

client = Inttegro::Client.new(api_key: ENV.fetch("INTTEGRO_API_KEY"))
result = client.message_templates.archive(
  template_id: "mtpl_WkPvqTrqGsopu07wfC7ttoWqmfwt48ZW7BGvYU",
  idempotency_key: "mtpl-archive-shipping-sms-001"
)
```

## Look up a message template

Retrieve one template by ID. Use lookup before editing, publishing, or showing a template detail view in your dashboard.

### Request body

- `id` — `string` — required — wire-only

  Template ID to retrieve.

### Response

Returns the matching [`message_template`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.MessageTemplate.html).

**Request — POST /message\_templates/lookup**

```ruby
require "inttegro"

client = Inttegro::Client.new(api_key: ENV.fetch("INTTEGRO_API_KEY"))
result = client.message_templates.lookup(template_id: "mtpl_WkPvqTrqGsopu07wfC7ttoWqmfwt48ZW7BGvYU")
```

## Page message templates

Retrieve a page of your templates, ordered by most recent update. Filter by
channel, locale, purpose, or status when building an operator dashboard.

### Request body

- `channel` — `enum` — wire-only

  Filter by [`Inttegro::MessageTemplate::Channel::SMS`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/Channel.html#SMS-constant) or
  [`Inttegro::MessageTemplate::Channel::EMAIL`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/Channel.html#EMAIL-constant).

- `locale` — `string` — wire-only

  Filter by locale.

- `page` — `integer` — wire-only

  1-based page number. Defaults to `1` when omitted or
  nonpositive.

- `purpose` — `string` — wire-only

  Filter by purpose.

- `size` — `integer` — wire-only

  Requested page capacity. Defaults to `25` when
  omitted or nonpositive.

- `status` — `enum` — wire-only

  Filter by [`Inttegro::MessageTemplate::Status::DRAFT`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/Status.html#DRAFT-constant),
  [`Inttegro::MessageTemplate::Status::PUBLISHED`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/Status.html#PUBLISHED-constant), or
  [`Inttegro::MessageTemplate::Status::ARCHIVED`](https://ruby.inttegro.dev/v10.0.0/Inttegro/MessageTemplate/Status.html#ARCHIVED-constant).

### Response

Returns a top-level [`page`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.Page.html) object.
[`page.number`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.Page.html) is the page number,
[`page.message_templates`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.Page.html) contains the returned records,
and response [`page.size`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.Page.html) is the number of records
actually returned rather than the requested capacity. Locale and purpose
filters are applied to the selected page, so a response can contain fewer
records than the requested capacity even when later records exist.

**Request — POST /message\_templates/page**

```ruby
require "inttegro"

client = Inttegro::Client.new(api_key: ENV.fetch("INTTEGRO_API_KEY"))
result = client.message_templates.page(
  page: 1,
  size: 25,
  channel: "sms",
  status: "published"
)
```

**Response**

```json
{
  "page": {
    "number": 1,
    "size": 1,
    "message_templates": [
      {
        "id": "mtpl_WkPvqTrqGsopu07wfC7ttoWqmfwt48ZW7BGvYU",
        "name": "Shipping update SMS",
        "channel": "sms",
        "purpose": "shipping_update",
        "locale": "en",
        "status": "published",
        "version": 1,
        "published_version": 1,
        "draft_version": 1,
        "has_unpublished_changes": false
      }
    ]
  }
}
```

## Render a message template preview

Render a template with variables before sending. Preview rendering is draft-aware, so operators can check unpublished changes before publishing. Chime send, schedule, and broadcast requests still require a published version.

### Request body

- `message_template` — wire-only

  Required. Template reference and render variables.

  - `message_template.template_id` — `string` — wire-only

    Required. Template ID to render.

  - `message_template.variables` — `object` — wire-only

    Values for the declared template variables.

### Response

Returns the template record plus rendered channel content. SMS previews
return [`rendered.sms.full_message`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.Preview.html). Email previews return
[`rendered.attachments`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.Preview.html),
[`rendered.channel`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.Preview.html), and a
[`rendered.email`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.Preview.html) object containing the rendered
[`rendered.email.from`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.Preview.html),
[`rendered.email.headers`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.Preview.html),
[`rendered.email.html`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.Preview.html),
[`rendered.email.reply_to`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.Preview.html),
[`rendered.email.safety`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.Preview.html),
[`rendered.email.subject`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.Preview.html), and
[`rendered.email.text`](https://ruby.inttegro.dev/v10.0.0/Inttegro/message_template.Preview.html) fields when applicable. Optional
fields are omitted rather than returned as
`nil`.

**Request — POST /message\_templates/render\_preview**

```ruby
require "inttegro"

client = Inttegro::Client.new(api_key: ENV.fetch("INTTEGRO_API_KEY"))
result = client.message_templates.render_preview(
  message_template: {
    template_id: "mtpl_WkPvqTrqGsopu07wfC7ttoWqmfwt48ZW7BGvYU",
    variables: {
      customer_name: "Gloria",
      tracking_url: "https://track.example.com/OR-12345",
    },
  }
)
```

**Response**

```json
{
  "message_template": {
    "id": "mtpl_WkPvqTrqGsopu07wfC7ttoWqmfwt48ZW7BGvYU",
    "name": "Shipping update SMS",
    "channel": "sms",
    "status": "published",
    "published_version": 1,
    "draft_version": 1
  },
  "rendered": {
    "channel": "sms",
    "sms": {
      "full_message": "Hi Gloria, your order shipped. Track it: https://track.example.com/OR-12345"
    }
  }
}
```

## Related resources

- [Send chime](https://studio.inttegro.com/machine/ruby/api/chimes.md#send-chime) - Send one notification with an inline or stored template.
- [Schedule chime](https://studio.inttegro.com/machine/ruby/api/chimes.md#schedule-chime) - Schedule notifications with stored template rendering.
- [Broadcast chimes](https://studio.inttegro.com/machine/ruby/api/chimes.md#broadcast-chimes) - Send one rendered template to a same-channel audience.
