# Templates API

> Learn how to manage email templates programmatically with the API.

Source: https://sendbroadcast.net/docs/api-templates

The Templates API provides full CRUD (Create, Read, Update, Delete) operations for managing reusable email templates. You can create, list, view, update, and delete templates programmatically to use across broadcasts, sequences, and transactional emails.

## Required Permissions

All endpoints require authentication via an API token with appropriate permissions:

- **Read Permission**: Required for GET endpoints (list, show)
- **Write Permission**: Required for POST, PATCH, DELETE endpoints

## Template Object

The template object contains the following fields:

| Field | Type | Description |
| --- | --- | --- |
| `id` | integer | The unique identifier of the template |
| `label` | string | The internal name of the template (must be unique per channel) |
| `subject` | string | The subject line of the email |
| `preheader` | string | Preview text that appears in email clients |
| `body` | string | The content of the email (plain text or HTML) |
| `html_body` | boolean | Whether the body contains HTML content (default: false) |
| `html_body_add_footer` | boolean | Whether the channel footer (with the unsubscribe link) is appended wherever this template is sent: sequence steps, confirmation emails and transactional emails made from it. Read for HTML templates only (default: true); rich text always gets the footer, and a block template derives it from whether its design has a Footer block. |
| `content_type` | string | `rich_text`, `html` or `blocks` (the [Drag-and-Drop Email Builder](https://sendbroadcast.net/docs/block-email-builder)) |
| `blocks_json` | object | The block document when `content_type` is `blocks`; `body` holds the rendered HTML |
| `created_at` | datetime | When the template was created |
| `template_purpose` | string | Either `general` (default) or `confirmation`. Set to `confirmation` to use the template for double opt-in confirmation emails. See [Confirmation Pages](https://sendbroadcast.net/docs/confirmation-pages). |
| `confirmation_text` | string | Legacy single-paragraph body for the success state of the confirmation page. Superseded by `confirmation_page_settings` but still honored as a fallback. Only meaningful when `template_purpose` is `confirmation`. |
| `default_confirmation` | boolean | When `true`, marks this template as the channel's default confirmation template. Setting `true` automatically unsets the flag on any other confirmation template in the same channel. |
| `confirmation_page_settings` | object | Per-state heading and body overrides for the confirmation page. Shape: `{ "<state>": { "heading": "...", "body": "..." } }` where `<state>` is one of `confirmed`, `already_confirmed`, `expired`, `not_found`, `confirmation_failed`, `fallback`. Only specified states/fields are applied; the rest fall back to defaults. |
| `updated_at` | datetime | When the template was last updated |

## List Templates

```
GET /api/v1/templates
```

Retrieve a list of all templates for the authenticated broadcast channel, ordered alphabetically by label.

### Query Parameters

- `limit` (optional): Maximum number of templates to return
- `offset` (optional): Number of templates to skip for pagination

### Request

```bash
curl -X GET \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  http://your-domain.com/api/v1/templates
```

### Response

```json
{
  "data": [
    {
      "id": 1,
      "label": "Monthly Newsletter",
      "subject": "Your Monthly Update",
      "preheader": "See what's new this month",
      "body": "<p>Newsletter content here</p>",
      "html_body": true,
      "template_purpose": "general",
      "confirmation_text": null,
      "default_confirmation": false,
      "confirmation_page_settings": {},
      "created_at": "2024-01-01T12:00:00Z",
      "updated_at": "2024-01-01T12:00:00Z"
    },
    {
      "id": 2,
      "label": "Subscription Confirmation",
      "subject": "Please confirm your subscription",
      "preheader": "One click to confirm",
      "body": "<p>Click <a href=\"{{ confirmation_url }}\">here</a> to confirm.</p>",
      "html_body": true,
      "template_purpose": "confirmation",
      "confirmation_text": "Thanks for confirming!",
      "default_confirmation": true,
      "confirmation_page_settings": {
        "confirmed": { "heading": "You're in!", "body": "Welcome to the list." }
      },
      "created_at": "2024-01-02T10:00:00Z",
      "updated_at": "2024-01-02T10:00:00Z"
    }
  ],
  "total": 2
}
```

## Get Template

```
GET /api/v1/templates/:id
```

Retrieve details of a specific template.

### Request

```bash
curl -X GET \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  http://your-domain.com/api/v1/templates/123
```

### Response

```json
{
  "id": 123,
  "label": "Welcome Email",
  "subject": "Welcome to Our Community!",
  "preheader": "Thanks for joining us",
  "body": "<p>Welcome to the community! We're excited to have you.</p>",
  "html_body": true,
  "template_purpose": "general",
  "confirmation_text": null,
  "default_confirmation": false,
  "confirmation_page_settings": {},
  "created_at": "2024-01-01T12:00:00Z",
  "updated_at": "2024-01-01T12:00:00Z"
}
```

## Create Template

```
POST /api/v1/templates
```

Create a new email template.

### Parameters

- `label` (required): Internal name of the template (must be unique per channel)
- `subject` (required): Subject line of the email
- `body` (required): Content of the email
- `preheader` (optional): Preview text that appears in email clients
- `html_body` (optional): Whether the body contains HTML (default: false)
- `html_body_add_footer` (optional): For HTML templates, whether the channel footer is appended wherever the template is sent (default: true). Ignored for rich text (always appended) and for `content_type: "blocks"` (decided by the design's Footer block)
- `template_purpose` (optional): `general` (default) or `confirmation`. Set to `confirmation` to use this template for double opt-in confirmation emails.
- `confirmation_text` (optional): Legacy success-state body for the confirmation page. Only meaningful when `template_purpose` is `confirmation`.
- `default_confirmation` (optional): Boolean. When `true`, this template becomes the channel's default confirmation template (any previous default is unset).
- `confirmation_page_settings` (optional): Per-state heading and body overrides for the confirmation page. See [Confirmation Pages](https://sendbroadcast.net/docs/confirmation-pages) for the resolution chain. Shape:

  ```json
  {
    "confirmed": { "heading": "...", "body": "..." },
    "expired":   { "heading": "...", "body": "..." }
  }
  ```

  Allowed states: `confirmed`, `already_confirmed`, `expired`, `not_found`, `confirmation_failed`, `fallback`.

### Request

```bash
curl -X POST \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "template": {
      "label": "Welcome Email",
      "subject": "Welcome to Our Community!",
      "preheader": "Thanks for joining us",
      "body": "<p>Welcome to the community! We are excited to have you.</p>",
      "html_body": true
    }
  }' \
  http://your-domain.com/api/v1/templates
```

### Response

```json
{
  "id": 123
}
```

### Notes

- The `label` must be unique within your broadcast channel
- If `html_body` is set to `true`, the body should contain valid HTML
- Line breaks in HTML should use `
` tags, and paragraphs should be wrapped in `

` tags ## Update Template
```
PATCH /api/v1/templates/:id
```

 Update an existing template. ### Parameters All parameters are optional. Only include the fields you want to update: - `label`: Internal name of the template - `subject`: Subject line of the email - `body`: Content of the email - `preheader`: Preview text that appears in email clients - `html_body`: Whether the body contains HTML - `html_body_add_footer`: Whether the channel footer is appended wherever the template is sent (see above) - `template_purpose`: `general` or `confirmation` - `confirmation_text`: Legacy success-state body for the confirmation page - `default_confirmation`: Boolean, set as channel default - `confirmation_page_settings`: Per-state page copy overrides (see Create above for shape) ### Request
```bash
curl -X PATCH \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "template": {
      "subject": "Updated Subject Line",
      "body": "<p>Updated content</p>"
    }
  }' \
  http://your-domain.com/api/v1/templates/123
```

 ### Response
```json
{
  "id": 123,
  "label": "Welcome Email",
  "subject": "Updated Subject Line",
  "preheader": "Thanks for joining us",
  "body": "<p>Updated content</p>",
  "html_body": true,
  "template_purpose": "general",
  "confirmation_text": null,
  "default_confirmation": false,
  "confirmation_page_settings": {},
  "created_at": "2024-01-01T12:00:00Z",
  "updated_at": "2024-01-01T12:30:00Z"
}
```

 ## Delete Template
```
DELETE /api/v1/templates/:id
```

 Delete a template. ### Request
```bash
curl -X DELETE \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  http://your-domain.com/api/v1/templates/123
```

 ### Response
```json
{
  "message": "Template deleted successfully"
}
```

 ## Channel Design (Brand Kit) `GET /api/v1/channel/design` returns the resolved brand kit of the token's channel, as set on **Settings → Brand Kit** (see [Drag-and-Drop Email Builder](https://sendbroadcast.net/docs/block-email-builder)). It needs the templates **read** permission. Defaults are filled in, so every field is always present; the logo is a public URL or `null`.

GET /api/v1/channel/design

bash

```
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  http://your-domain.com/api/v1/channel/design
```

json

```
{
  "colors": { "page_background": "#f4f4f5", "body_background": "#ffffff", "text": "#18181b",
              "muted": "#71717a", "link": "#2563eb", "accent": "#ff5500", "button_text": "#ffffff" },
  "typography": { "font": "georgia", "font_stack": "Georgia,'Times New Roman',Times,serif" },
  "layout": { "width": 600, "radius": 4 },
  "brand": {
    "logo_url": "https://your-domain.com/files/abc123",
    "logo_width": 180,
    "website_url": "https://acme.example",
    "social_links": [ { "network": "x", "url": "https://x.com/acme" } ],
    "social_icon_style": "dark"
  }
}
```

## Error Responses

If the request is invalid, the response will include an appropriate HTTP status code and error message:

### 401 Unauthorized

```json
{
  "error": "Unauthorized"
}
```

This error occurs when:
- No authorization header is provided
- The token is invalid or expired
- The token doesn't have the required permissions

### 404 Not Found

```json
{
  "error": "Template not found"
}
```

This error occurs when:
- The template ID doesn't exist
- The template belongs to a different broadcast channel

### 422 Unprocessable Entity

```json
{
  "error": "Label can't be blank, Subject can't be blank, Body can't be blank"
}
```

This error occurs when:
- Required fields are missing
- The label is already taken by another template in the same channel
- Validation fails for any other reason

## Usage Example: Syncing Templates from External System

Here's an example of how you might sync templates from an external system:

```bash
# First, list existing templates
curl -X GET \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  http://your-domain.com/api/v1/templates

# Create a new template if it doesn't exist
curl -X POST \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "template": {
      "label": "Product Update",
      "subject": "New Product Features",
      "preheader": "Check out what is new",
      "body": "<h1>New Features</h1><p>We have exciting updates to share!</p>",
      "html_body": true
    }
  }' \
  http://your-domain.com/api/v1/templates

# Update an existing template
curl -X PATCH \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "template": {
      "body": "<h1>New Features</h1><p>Updated content with more details!</p>"
    }
  }' \
  http://your-domain.com/api/v1/templates/123
```
