# Templates

Template là mẫu email cả đội soạn một lần và gửi nhiều lần: xác nhận đơn hàng, đặt lại mật khẩu, thư chào mừng. Bạn soạn HTML, khai báo biến, publish, rồi gửi chỉ với id hoặc alias của template cùng giá trị các biến. API giống Resend Templates.

## Trước khi bắt đầu

- Quản lý template qua API cần key có `email:write`. Key chỉ dùng để gửi bằng template thì cấp `email:send`.
- Địa chỉ `from` của template, hoặc địa chỉ bạn truyền khi gửi, phải thuộc tên miền đã xác minh.

## Soạn và publish

Mở **Email → Templates → Template mới**. Trình soạn có:

- **Giá trị mặc định**: người gửi, tiêu đề, Reply-To và thư mục. Lệnh gửi có thể ghi đè từng giá trị.
- **HTML** có tô màu cú pháp, tab **Xem trước** điền sẵn giá trị fallback, và tab **Văn bản**. Để trống phần văn bản thì Hạ Tầng tự tạo từ HTML.
- **Biến**: khai báo mọi biến dùng trong tiêu đề và nội dung, kiểu `string` hoặc `number`, kèm fallback tuỳ chọn. **Khai báo tất cả** thêm những biến Hạ Tầng tìm thấy trong nội dung.
- **Kiểm tra link** báo các link trống, chỉ có `#`, dùng tên miền mẫu (`example.com`, `yourdomain.com`, `localhost`…), không phải `http(s)`, không mở được, hoặc trả về trang lỗi. Link có vấn đề sẽ chặn publish cho tới khi bạn chọn **Vẫn publish**.
- **Gửi thử** tới địa chỉ của bạn, **Nhân bản** và **Publish**.

Chỉ bản đã publish mới gửi được. Bạn vẫn sửa tiếp bản nháp được: lệnh gửi tiếp tục dùng bản đã publish cho tới lần publish sau. Danh sách hiện **Có thay đổi chưa publish** khi bản nháp khác bản đã publish.

## Biến

Viết biến dạng `{{{NAME}}}`, hoặc `{{{NAME|giá trị mặc định}}}` để kèm giá trị mặc định ngay tại chỗ:

```html
<p>Chào {{{NAME|bạn}}}, đơn {{{ORDER}}} trị giá {{{TOTAL}}}đ đã được xác nhận.</p>
```

- Khoá gồm chữ, số và `_`, tối đa 50 ký tự. Mỗi template khai báo tối đa 50 biến, mỗi giá trị tối đa 2.000 ký tự.
- Giá trị được escape khi chèn vào phần HTML.
- Biến kiểu `number` từ chối giá trị không phải số.
- Giá trị lấy từ lệnh gửi; nếu không có thì lấy giá trị mặc định tại chỗ; nếu vẫn không có thì lấy fallback đã khai báo. Biến không có cả ba thì lệnh gửi bị từ chối với `422` và không thư nào được gửi.
- Không publish được khi nội dung dùng biến chưa khai báo.
- Các tên sau được giữ sẵn và được chiến dịch email, automations điền cho từng người nhận: `{{{FIRST_NAME}}}`, `{{{LAST_NAME}}}`, `{{{EMAIL}}}`, `{{{UNSUBSCRIBE_URL}}}` (và tên khác của nó `{{{RESEND_UNSUBSCRIBE_URL}}}`). Thuộc tính contact dùng dạng `{{{contact.plan}}}`; xem [Contacts, segments và topics](https://hatang.dev/vi/docs/guides/email/audiences.md). Bạn không cần khai báo các biến này.

## Gửi bằng template

**cURL**

```bash
curl -X POST https://api.hatang.dev/emails \
  -H "Authorization: Bearer $HATANG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": ["khach@example.vn"],
    "template": {
      "id": "order-confirmation",
      "variables": { "NAME": "Lan", "ORDER": "DH1024", "TOTAL": 450000 }
    }
  }'
```

**Node.js**

```ts
const { data, error } = await hatang.emails.send({
  to: "khach@example.vn",
  template: { id: "order-confirmation", variables: { NAME: "Lan", ORDER: "DH1024", TOTAL: 450000 } },
});
```

**Python**

```python
hatang.emails.send({
    "to": ["khach@example.vn"],
    "template": {"id": "order-confirmation", "variables": {"NAME": "Lan", "ORDER": "DH1024", "TOTAL": 450000}},
})
```

**PHP**

```php
$res = $client->post('/emails', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('HATANG_API_KEY')],
    'json' => [
        'to' => ['khach@example.vn'],
        'template' => ['id' => 'order-confirmation', 'variables' => ['NAME' => 'Lan', 'ORDER' => 'DH1024', 'TOTAL' => 450000]],
    ],
]);
```

- `template.id` là id template (`tpl_…`) hoặc alias.
- `from`, `subject` và `reply_to` trong request ghi đè giá trị mặc định của template. Bắt buộc nếu template không có.
- Không gửi `html` hay `text` cùng với `template`.
- `POST /emails/batch` nhận `template` ở từng phần tử.
- Để tạo chiến dịch email từ template, truyền `template_id` cho `POST /broadcasts`, hoặc chọn **Bắt đầu từ template** trong trình soạn chiến dịch. Xem [Chiến dịch email](https://hatang.dev/vi/docs/guides/email/broadcasts.md).

| Lỗi | Nguyên nhân |
|---|---|
| `404 not_found` | Không có template nào có id hoặc alias này. |
| `422 validation_error` "is not published yet" | Hãy publish template trước. |
| `422 validation_error` "Missing value for template variable" | Một biến không có giá trị, không có mặc định tại chỗ và không có fallback. |
| `422 validation_error` "The template has no `from`" | Truyền `from` trong request hoặc đặt cho template. |

## Quản lý template bằng API

```bash
curl -X POST https://api.hatang.dev/templates \
  -H "Authorization: Bearer $HATANG_API_KEY" -H "Content-Type: application/json" \
  -d '{
    "name": "Xác nhận đơn hàng",
    "alias": "order-confirmation",
    "from": "Shop <orders@shop.vn>",
    "subject": "Đơn {{{ORDER}}} đã được xác nhận",
    "html": "<p>Chào {{{NAME|bạn}}}, đơn {{{ORDER}}} trị giá {{{TOTAL}}}đ đã được xác nhận.</p>",
    "variables": [
      { "key": "NAME", "type": "string" },
      { "key": "ORDER", "type": "string" },
      { "key": "TOTAL", "type": "number", "fallback_value": 0 }
    ]
  }'
# { "object": "template", "id": "tpl_…" }

curl -X POST https://api.hatang.dev/templates/order-confirmation/publish -H "Authorization: Bearer $HATANG_API_KEY"
# { "object": "template", "id": "tpl_…", "current_version_id": "tplv_…" }
```

| Endpoint | Mô tả |
|---|---|
| `POST /templates` | Tạo bản nháp: `name`, `html` (bắt buộc), `alias`, `from`, `subject`, `reply_to`, `text`, `variables`, `folder`. |
| `GET /templates` | Danh sách template. Lọc theo `q` (tên hoặc alias), `folder`, `status` (`draft` hoặc `published`), cùng `limit` và `after`. |
| `GET /templates/{id hoặc alias}` | Một template, kèm `status`, `current_version_id`, `published_at` và `has_unpublished_versions`. |
| `PATCH /templates/{id hoặc alias}` | Sửa bản nháp. |
| `POST /templates/{id hoặc alias}/publish` | Publish bản nháp. |
| `POST /templates/{id hoặc alias}/duplicate` | Nhân bản thành bản nháp mới có tên "(copy)". |
| `DELETE /templates/{id hoặc alias}` | Xoá. |

Alias gồm chữ thường, số, `-` và `_`, tối đa 64 ký tự, và không trùng trong doanh nghiệp. SDK Node.js có các lệnh tương ứng trong `hatang.templates`: `create`, `get`, `list`, `update`, `publish`, `duplicate` và `remove`.

## Bước tiếp theo

- [Gửi email](https://hatang.dev/vi/docs/guides/email/sending.md)
- [Chiến dịch email](https://hatang.dev/vi/docs/guides/email/broadcasts.md)
- [Automations](https://hatang.dev/vi/docs/guides/email/automations.md)

Source: https://hatang.dev/vi/docs/guides/email/templates
