# Create Template

`POST https://api.inboxjot.com/v1/templates`

Creates a template. Send the email as `html`, or start from a ready-made design with `starter_id`. With neither, the template starts empty. Needs a Full key. A key limited to one domain answers 403. Send an optional `Idempotency-Key` header to retry safely. See Idempotency.

Send it with Send Email by passing its id as `template.id`.

## Body Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | Yes | The template name, 1 to 200 characters. |
| `from` | string \| null | No | The default from address, up to 320 characters. |
| `reply_to` | string \| null | No | The default reply-to address. Send `null` to clear it. |
| `subject` | string \| null | No | The subject, up to 998 characters, without line breaks. |
| `preheader` | string \| null | No | The preview text, up to 500 characters, without line breaks. |
| `html` | string \| null | No | The email as HTML. Inboxjot turns it into editor content, so the template stays editable in the dashboard. |
| `content` | object \| null | No | The editor document, as the dashboard saves it. Most callers send `html` instead. When you send both, `html` wins. |
| `starter_id` | string \| null | No | A ready-made design: `welcome`, `verify-email`, `password-reset`, `receipt`, `newsletter`, `product-launch`, `event-invite` or `re-engagement`. Ignored when you send `html`. |

## Response

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | No | The template id. |
| `name` | string | No | The template name. |
| `from` | string | No | The default from address. |
| `reply_to` | string \| null | No | The default reply-to address. |
| `subject` | string | No | The subject. |
| `preheader` | string | No | The preview text. |
| `html` | string | No | The rendered HTML. |
| `text` | string | No | The plain text version. |
| `published_version_id` | string \| null | No | The version that sends use. `null` until the first publish, and sends fail until then. |
| `has_unpublished_changes` | boolean | No | Whether the draft differs from the version that sends use. |
| `created_at` | string | No | When it was created. |
| `updated_at` | string | No | When it last changed. |

## Request

cURL:

```bash
curl -X POST https://api.inboxjot.com/v1/templates \
  -H "Authorization: Bearer $INBOXJOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Welcome",
    "from": "Acme <hello@acme.dev>",
    "subject": "Welcome to Acme, {{first_name}}",
    "html": "<h1>Welcome, {{first_name}}</h1><p>Here is how to get started.</p>"
  }'
```

## Responses

| Status | Description |
| --- | --- |
| 201 | Created the template. |
| 400 | A field is missing or invalid, or the Idempotency-Key header is not valid. |
| 401 | The API key is missing, revoked or expired. |
| 403 | The key is a Sending key or is limited to one domain, or the request comes from outside its IP allowlist. |
| 404 | The starter does not exist. |
| 409 | A request with the same Idempotency-Key is still running. Retry after one second. |
| 413 | The body is larger than 2 MB. |
| 415 | The Content-Type header is not application/json. |
| 422 | The Idempotency-Key was already used with a different request. |
| 429 | Too many requests for this key. Wait for the seconds in the Retry-After header. |
| 500 | Something failed on our side. Retry later. |

201:

```json
{
  "id": "tpl_06d2mfk8r5cx3nd8vt1qa",
  "name": "Welcome",
  "from": "Acme <hello@acme.dev>",
  "reply_to": null,
  "subject": "Welcome to Acme, {{first_name}}",
  "preheader": "Here is how to get started",
  "html": "<!DOCTYPE html><html>…</html>",
  "text": "Hi Suhasinee, welcome to Acme…",
  "published_version_id": "ver_06d2mfk8r5cx3nd8vt1qb",
  "has_unpublished_changes": false,
  "created_at": "2026-10-21T09:00:00.000Z",
  "updated_at": "2026-10-21T09:00:00.000Z"
}
```

400:

```json
{
  "name": "validation_error",
  "status": 400,
  "message": "The request body is not valid JSON",
  "errors": [
    {
      "message": "The request body is not valid JSON",
      "location": "body"
    }
  ],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

401:

```json
{
  "name": "unauthorized",
  "status": 401,
  "message": "Unauthorized",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

403:

```json
{
  "name": "forbidden",
  "status": 403,
  "message": "This key cannot be used from 203.0.113.7",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

404:

```json
{
  "name": "not_found",
  "status": 404,
  "message": "Starter not found",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

409:

```json
{
  "name": "concurrent_idempotent_requests",
  "status": 409,
  "message": "A request with this idempotency key is still in progress. Try again later.",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

413:

```json
{
  "name": "payload_too_large",
  "status": 413,
  "message": "The request body is too large",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

415:

```json
{
  "name": "unsupported_media_type",
  "status": 415,
  "message": "The Content-Type must be application/json",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

422:

```json
{
  "name": "invalid_idempotent_request",
  "status": 422,
  "message": "This idempotency key was already used with a different request",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

429:

```json
{
  "name": "rate_limit_exceeded",
  "status": 429,
  "message": "Too many attempts. Try again later.",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```

500:

```json
{
  "name": "unknown_error",
  "status": 500,
  "message": "Something went wrong. Please try again later.",
  "errors": [],
  "request_id": "5f0c6a2e-8d1b-4c7a-9e3f-2b6d4a1c8e90"
}
```
