# Create an invite template

Source: https://api-docs.magicdoor.com/api-reference/tenant-portal-invite-templates/create-invite-template

Adds a company-authored tenant portal invite template. The new template's `kind` is always `Custom`. Requires the `settings:write` permission.

`POST https://services.magicdoor.com/settings/company-portal/settings/tenant-portal-invite-templates`

**Authentication:** bearer token in the `Authorization` header, as `Bearer <token>`.

## Body

Content type: `application/json`

- `name` (string, required) — What to call the template. If the company already has a template with this name, a number is appended to make it unique.
- `email` (object, required) — The email version of the message.
  - `subject` (string, required) — The email subject line.
  - `body` (string, required) — The email body, as HTML.
- `text` (object, required) — The text-message version of the message.
  - `body` (string, required) — The text message body, as plain text.

```json
{
  "name": "Renewal reminder",
  "email": {
    "subject": "A quick reminder from {CompanyName}",
    "body": "<p>Hi {TenantName}, sign in at {PortalLink} to review your lease.</p>"
  },
  "text": {
    "body": "Hi {TenantName}, review your lease at {PortalLink}"
  }
}
```

## Example request

```bash
curl --request POST \
  --url 'https://services.magicdoor.com/settings/company-portal/settings/tenant-portal-invite-templates' \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "Renewal reminder",
  "email": {
    "subject": "A quick reminder from {CompanyName}",
    "body": "<p>Hi {TenantName}, sign in at {PortalLink} to review your lease.</p>"
  },
  "text": {
    "body": "Hi {TenantName}, review your lease at {PortalLink}"
  }
}'
```

## Responses

### 200 — The template that was created.

- `id` (string, required) — The template's Snowflake id, as a decimal string.
- `kind` (enum<string>, required) — Which message in the invite sequence this template is. Everything the company creates itself is `Custom`. One of: `Welcome`, `PortalInvite`, `Payment`, `PasswordChange`, `Custom`, `PostInviteMaintenance`, `PostInviteImportantDocuments`.
- `name` (string, required) — What the template is called in the settings screen.
- `isCustom` (boolean, required) — `true` for templates the company created, `false` for MagicDoor's built-in ones. Only custom templates can be deleted, and only built-in ones can be reset.
- `email` (object, required) — The email version of the message.
  - `subject` (string, required) — The email subject line.
  - `body` (string, required) — The email body, as HTML.
- `text` (object, required) — The text-message version of the message.
  - `body` (string, required) — The text message body, as plain text.
- `updatedAt` (string, required) — When the template was last saved, formatted as `yyyy-MM-dd HH:mm`. Unlike timestamps elsewhere in the API this is a display string, not an ISO 8601 value.
- `updatedByName` (string) — The property manager who last saved it, as a first name and last initial. Absent when the last save was not made by a property manager.

```json
{
  "id": "1849037281920516097",
  "kind": "Custom",
  "name": "Renewal reminder",
  "isCustom": true,
  "email": {
    "subject": "A quick reminder from {CompanyName}",
    "body": "<p>Hi {TenantName}, sign in at {PortalLink} to review your lease.</p>"
  },
  "text": {
    "body": "Hi {TenantName}, review your lease at {PortalLink}"
  },
  "updatedAt": "2026-08-17 21:04",
  "updatedByName": "Dana K."
}
```

### 400 — A required field is missing from the body.

### 401 — The access token is missing, expired, or invalid.

### 403 — The caller does not hold the `settings:write` permission.

> **Note:**
>
> A name already in use is not rejected. MagicDoor appends a number — `Renewal reminder 1`, then `Renewal reminder 2` — and returns the name it settled on.
