# Template API - Fields Reference

This article describes all fields available through the Template API. Use this as a reference when reading, creating, or updating templates.

---

## Overview

The Template API lets you manage your Envoke email templates programmatically — create new templates, update existing ones, and retrieve template details including HTML content. Templates can be assigned to groups, tagged with a language, and toggled between published and unpublished states.

All endpoints require [HTTP Basic Auth](https://envoke-developers.pages.dev/guides/authentication/) using your API ID and API Key.

---

## Fields

| Field | Type | Read-only | Required on Create | Description |
|---|---|---|---|---|
| `id` | string | Yes | — | Unique identifier assigned on creation. Returned as a string. |
| `external_id` | string | Yes | — | Randomly assigned identifier used to build the preview URL. |
| `preview_url` | string | Yes | — | Public URL to preview the template in a browser. |
| `name` | string | No | No | Template name. Minimum 3 characters. Auto-generated if omitted. |
| `status` | string (enum) | No | No | `published` or `unpublished`. Defaults to `published` on create if not specified. |
| `language` | string | No | No | IETF language code (e.g. `en`, `fr`). Defaults to `en`. |
| `group` | string | No | No | Name of the group the template belongs to. Empty string (`""`) when unset. |
| `create_time` | string | Yes | — | Timestamp when the template was created. |
| `modified_time` | string | Yes | — | Timestamp when the template was last modified. |
| `html` | string | — | See below | Full HTML content. Write on create/update; read only via `?include_html=1`. |

---

## Field Details

### `id`

- **Type:** String
- **Read-only:** Yes — assigned automatically on creation.
- **Example:** `"42"`

Used to identify the template in update, delete, and single-record GET requests.

---

### `external_id`

- **Type:** String
- **Read-only:** Yes — assigned automatically on creation.
- **Example:** `"a1b2c3d4e5f6g7h8"`

A randomly assigned identifier. Not the same as `id`. Used to construct the `preview_url`.

---

### `preview_url`

- **Type:** String
- **Read-only:** Yes — computed from the account's external ID and the template's `external_id`.
- **Format:** `https://{domain}/m/{account_external_id}/m/{external_id}`
- **Example:** `"https://engage.envoke.com/m/acme-corp/m/a1b2c3d4e5f6g7h8"`

A public URL that shows the template in a browser without logging in. `{domain}` is your account's custom domain if it has one, and otherwise Envoke's message domain; it is not the API host. Use the URL as returned rather than building it yourself.

---

### `name`

- **Type:** String
- **Read-only:** No — updatable via PATCH.
- **Required on create:** No — if omitted, auto-generated as `API Template {timestamp}`.
- **Validation:** Minimum 3 characters (applies when provided).
- **Example:** `"Welcome Email"`

---

### `status`

- **Type:** String (enum)
- **Read-only:** No — updatable via PATCH.
- **Required on create:** No
- **Allowed values:** `published`, `unpublished`

Controls whether the template is available for use in campaigns.

On create, `status` defaults to `published` if not specified. Pass `"unpublished"` to create the template in a draft state. On PATCH, accepted values are `"published"` and `"unpublished"`.

---

### `language`

- **Type:** String
- **Read-only:** No — updatable via PATCH.
- **Required on create:** No — defaults to `en`.
- **Accepted values (write):** IETF language code (e.g. `en`) or numeric language ID.
- **Returned value (read):** Always the IETF language code.
- **Example:** `"en"`, `"fr"`

Common supported codes: `en`, `fr`, `ar`, `zh`, `de`, `it`, `ja`, `ko`, `pt`, `ru`, `es`.

---

### `group`

- **Type:** String
- **Read-only:** No — updatable via PATCH.
- **Required on create:** No
- **Accepted values (write):** Group name (string) or group ID (integer). The group must be of type `message_template`. Pass an empty string (`""`) to remove the group assignment.
- **Returned value (read):** The group name as a string. Returns `""` (empty string) when no group is assigned.
- **Example:** `"Marketing Templates"`, `""`

---

### `create_time`

- **Type:** String
- **Read-only:** Yes
- **Format:** `Y-m-d H:i:s` in the account's configured timezone.
- **Example:** `"2026-04-11 09:00:00"`

---

### `modified_time`

- **Type:** String
- **Read-only:** Yes
- **Format:** `Y-m-d H:i:s` in the account's configured timezone.
- **Example:** `"2026-04-11 14:22:10"`

Updated automatically whenever the template is saved.

---

### `html`

- **Type:** String
- **Maximum size:** 200 KB
- **Write:** Accepted in POST (create) and PATCH (update) request bodies.
- **Read:** Only returned on `GET /v2/templates/{id}?include_html=1`. Never included in list responses or in create/update response bodies.

The full HTML source of the template. On create, either `html` or `template_id` must be provided (see below).

---

## Write-Only Field: `template_id`

| Field | Type | Operations | Description |
|---|---|---|---|
| `template_id` | integer | POST only | ID of an existing template or message to copy HTML from. |

`template_id` is a write-only convenience field for creating a new template by copying the HTML from an existing one. It is never returned in any GET response. The source must be owned by your account or accessible as a shared template.

Either `html` or `template_id` must be provided when creating a template. `name` is optional — if omitted, the template is named `API Template {timestamp}`. If neither `html` nor `template_id` is included, the request will fail with a validation error.

---

## Error Responses

**Validation errors** (missing fields, invalid values, name too short, etc.):

```json
{
  "success": false,
  "result_text": "Validation failed, see 'result_data' -> 'errors'",
  "result_data": {
    "errors": [
      "The field 'name' must be at least 3 characters long"
    ]
  }
}
```

Some errors also include an `allowed_values` object listing the valid options for the offending field:

```json
{
  "success": false,
  "result_text": "Validation failed, see 'result_data' -> 'errors'",
  "result_data": {
    "errors": ["Invalid 'status'"],
    "allowed_values": {
      "status": ["published", "unpublished"]
    }
  }
}
```

**Not-found behaviour varies by method:**

- **GET** `/templates/{id}` — when the ID is not found, returns an empty array (`[]`).
- **PATCH** `/templates/{id}` — when the ID is not found, returns a validation error:

```json
{
  "success": false,
  "result_text": "Validation failed, see 'result_data' -> 'errors'",
  "result_data": {
    "errors": ["Item with id '999999' not found"]
  }
}
```

- **DELETE** `/templates/{id}` — when the ID is not found, returns a validation error:

```json
{
  "success": false,
  "result_text": "Validation failed, see 'result_data' -> 'errors'",
  "result_data": {
    "errors": ["Item with id '999999' not found"]
  }
}
```

---

*Full reference, OpenAPI description, and Postman collection: [developers.envoke.com](https://developers.envoke.com).*
