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

# Email Templates API

> Read and manage the email templates and snippets people use in the composer, Inbox replies and sequence steps.

Email templates are whole emails (a name, a subject and a body) that people insert in the one-to-one composer, Inbox replies and sequence steps. Snippets are short blocks inserted while writing, by typing `/` and their shortcut. Both live in the same resource and differ by `kind`.

Templates are either **shared** with the workspace (`visibility: "team"`: every member can use them, editors and admins change them) or **personal** (`visibility: "personal"`: only their owner sees them). An API key or OAuth token acts as the person who owns it, so it sees the shared templates plus that person's own.

## Scopes

| Scope | Allows |
| - | - |
| `sequences:read` | List and read templates and snippets |
| `sequences:write` | Create, update and delete templates and snippets |

A viewer's credential can read but not write.

## Endpoints

| Method | Endpoint | Description |
| - | - | - |
| `GET` | `/api/v1/email-templates` | List templates and snippets. Filters: `kind` (`template` or `snippet`), `visibility` (`team` or `personal`), `search` (name). Paginated with `page` and `per_page` (max 100) |
| `POST` | `/api/v1/email-templates` | Create one |
| `GET` | `/api/v1/email-templates/:id` | Get one |
| `PATCH` | `/api/v1/email-templates/:id` | Change the name, subject, body, shortcut or visibility |
| `DELETE` | `/api/v1/email-templates/:id` | Delete it. Sequence steps and emails already written from it keep their own copy |

## The template object

```json theme={null}
{
  "id": "4c1b2f7e-…",
  "team_id": "a0e1…",
  "kind": "template",
  "visibility": "team",
  "owner_id": null,
  "name": "Follow-up after demo",
  "subject": "Next steps for {{ company.name }}",
  "body_html": "<p>Hi {{ contact.first_name | there }},</p><p>Thanks for your time today…</p>",
  "shortcut": null,
  "created_by": "9f3e…",
  "updated_by": "9f3e…",
  "created_at": "2026-10-30T14:02:11Z",
  "updated_at": "2026-10-30T14:02:11Z"
}
```

| Field | Notes |
| - | - |
| `kind` | `template` (default) or `snippet`; it can't be changed later |
| `visibility` | `personal` (default) or `team`. A personal template's `owner_id` is its owner; a shared one has none. Making a shared template personal makes it yours |
| `name` | Required, up to 120 characters |
| `subject` | Templates only, up to 200 characters, optional |
| `body_html` | Required, up to 100,000 characters. HTML is sanitized (scripts, event handlers and unsafe links are removed); plain text is turned into paragraphs |
| `shortcut` | Snippets only: letters, numbers and dashes, up to 30. Defaults to one made from the name |

## Merge fields

Subjects and bodies use the same merge fields as sequences. They are filled in for each recipient when an email is sent:

| Group | Fields |
| - | - |
| Contact | `contact.first_name`, `contact.last_name`, `contact.full_name`, `contact.email`, `contact.phone`, `contact.company`, `contact.job_title`, and `contact.<field_name>` for each custom contact field |
| Company | `company.name`, `company.domain`, `company.industry`, `company.location`, `company.phone` (the contact's company) |
| Deal | `deal.name`, `deal.amount`, `deal.stage`, `deal.close_date` (the contact's open deal, else their most recent one) |
| Sender | `sender.first_name`, `sender.full_name`, `sender.email`, `sender.meeting_link` (the sending person's default booking page) |

Write a field as `{{ contact.first_name }}`. Add a fallback for when the field is empty with a pipe: `{{ contact.first_name | there }}`. A field with no value and no fallback is left blank. The bare names older sequences use still work: `{{first_name}}`, `{{last_name}}`, `{{full_name}}`, `{{name}}`, `{{email}}`, `{{phone}}`, `{{company}}`, `{{company_name}}`, `{{job_title}}`, `{{title}}`, `{{rep_name}}`, `{{sender_name}}` and `{{meeting_link}}`.

Anything else inside `{{ }}` is not a merge field and is never sent as typed: the API refuses to save it (`400`), the composer refuses to send it, and a sequence can't be activated with one.

## Example

```bash theme={null}
curl -X POST https://orbitforms.ai/api/v1/email-templates \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Pricing overview",
    "kind": "snippet",
    "visibility": "team",
    "shortcut": "pricing",
    "body_html": "<p>Our Pro plan starts at a flat monthly price per seat. Happy to walk you through it, {{ contact.first_name | there }}.</p>"
  }'
```

## Errors

| Status | When |
| - | - |
| `400` | Invalid input, including an unknown merge field (`error_description` names it), a subject on a snippet or a shortcut on a template |
| `403` | The credential lacks the scope, or belongs to a viewer (writes) |
| `404` | No such template, or it is someone else's personal template |

> **[Templates guide](https://docs.orbitforms.ai/guides/email-templates.md)**
>
> Templates, snippets, signatures, attachments and send later

> **[Sequences API](https://docs.orbitforms.ai/developers/api/sequences.md)**
>
> Enroll contacts in sequences


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.