---
title: "Add a template from the gallery"
description: "Add one of the gallery's ready-made emails (unitpost.com/templates) to your workspace as a draft Design template, as the gallery's \"Use this template\" does. `POST /api/v1/email/templates/from-library`"
url: https://www.unitpost.com/docs/email/post-email-templates-from-library
section: "Email API reference"
updated: 2026-10-13
---
# Add a template from the gallery

`POST /api/v1/email/templates/from-library`

Add one of the gallery's ready-made emails (unitpost.com/templates) to your workspace as a draft Design template, as the gallery's "Use this template" does. `slug` names it; the ones marked for paid plans answer `403 limit_reached` on the free plan. Edit it with [Update a template](https://www.unitpost.com/docs/email/patch-email-templates-id). Pass an `Idempotency-Key` so a retry returns the same template. Requires the `templates:write` capability.

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | string | no | Any unique string (1–256 characters, e.g. a UUID). Retrying with the same key and the same body within 24 hours returns the first result instead of sending again; the same key with a different body is `409 invalid_idempotent_request`, and one still in flight is `409 concurrent_idempotent_requests`. |

## Request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `slug` | string | yes | The gallery email to add (unitpost.com/templates): `welcome`, `password-reset`, `email-verification`, `magic-link`, `receipt`, `invoice`, `team-invite`, `shipping-confirmation`, `subscription-renewal`, `trial-ending`, `security-alert`, `comment-mention`, `newsletter`, `july-newsletter`, `product-announcement`, `event-invite`, `discount-offer`, `re-engagement`, `feedback-survey`, `waitlist-invite`, `abandoned-cart`, `case-study`, `webinar-recap`, `referral`. |
| `name` | string | no | The template's name. Default: the gallery email's. |

## Response fields (201)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `object` | string | yes | — |
| `id` | string | yes | — |
| `name` | string | yes | — |
| `subject` | string \| null | yes | — |
| `status` | enum | yes | One of: `draft`, `published`. |
| `editor` | enum | no | Which editor this template is authored in — and so which body field updates it. `design`: built from @unitpost/email components (the dashboard's Design tab) — update with `tsx`. `simple`: a plain, personal Gmail-style email (the Simple tab) — update with `text`. `code`: raw HTML (the Code tab) — update with `html`. Keep the editor unless the user asked to switch; to switch, send the other body field or `editor` alone to convert the current body. One of: `simple`, `design`, `code`. |
| `kind` | enum | yes | The coarse kind: `simple` (editor `simple`) or `designed` (editor `design` or `code`). Prefer `editor`. One of: `simple`, `designed`. |
| `preview_text` | string | no | Inbox preview text: the snippet most inboxes show after the subject. Empty when unset. |
| `category` | enum | no | `marketing` (a campaign can send it; it gets the unsubscribe footer at send) or `transactional` (receipts, sign-in codes, notifications: no footer, and campaigns refuse it). Change it with `category` on an update. One of: `transactional`, `marketing`. |
| `html` | string \| null | no | — |
| `tsx` | string \| null | no | A `design` template's body as @unitpost/email component TSX, wrapped in the `<Email …>` element that carries its theme, preview text and category — edit it and send it back as `tsx`. Null for `simple` and `code` templates. Present on single reads; omitted from list rows. |
| `text` | string \| null | no | A `simple` template's body in the Simple `text` format: edit it and send it back as `text`. Null for `design` and `code` templates, and for a Simple email the format can't carry whole (an indented line): change that one in the dashboard, or send a whole new `text`. Present on single reads; omitted from list rows. |
| `warnings` | string[] | no | Create or update only: what changed that you didn't write, in plain words — markup the Simple format removed from `text`, `<Email>` attributes or theme values that were ignored, what an `editor` conversion flattened or couldn't keep, a `tsx` write that switched the template's editor. Absent when nothing did. Tell the user. |
| `created_at` | string | yes | — |
| `updated_at` | string | yes | — |

## Responses

| Status | Description |
| --- | --- |
| 201 | The new template. |
| 400 | The body isn't JSON. |
| 401 | Missing or invalid API key. |
| 403 | Insufficient scope, or a paid-plan gallery email on the free plan (`limit_reached`). |
| 409 | The `Idempotency-Key` is in use by a request still running, or with another body. |
| 422 | An unknown `slug`, a bad `name`, or an unknown key. |

## Example request

```bash
curl -X POST 'https://www.unitpost.com/api/v1/email/templates/from-library' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'User-Agent: my-app/1.0' \
  -H 'Content-Type: application/json' \
  -d '{
    "slug": "welcome"
  }'
```

## Example response (201)

```json
{
  "object": "template",
  "id": "id_123",
  "name": "Example",
  "subject": "Welcome to Acme",
  "status": "draft",
  "editor": "simple",
  "kind": "simple",
  "preview_text": "string",
  "category": "transactional",
  "html": "string",
  "tsx": "string",
  "text": "string",
  "warnings": [
    "string"
  ],
  "created_at": "2026-01-01T00:00:00.000Z",
  "updated_at": "2026-01-01T00:00:00.000Z"
}
```

## Links

- HTML reference (with Node.js, Python, Ruby, PHP, Laravel, Go, Java, Rust, .NET and CLI examples): https://www.unitpost.com/docs/email/post-email-templates-from-library
- OpenAPI 3.1 (full schemas): https://www.unitpost.com/api/v1/openapi.json
