Skip to main content

Templates

A template is an email your team writes once and sends many times: an order confirmation, a password reset, a welcome email. You write the HTML, declare its variables, publish it, and then send it with just its id or alias and the variable values. The API works like Resend Templates.

Before you start​

  • Managing templates through the API needs a key with email:write. For a key that only sends with templates, grant email:send.
  • The template's from address, or the one you pass when sending, must be on a verified domain.

Write and publish​

Open Email → Templates → New template. The editor has:

  • Defaults: sender, subject, Reply-To and folder. A send can override each of them.
  • HTML with syntax highlighting, a Preview tab filled with the fallback values, and a Plain text tab. Leave plain text empty and Ha Tang generates it from the HTML.
  • Variables: declare every variable the subject and body use, as string or number, with an optional fallback. Declare all adds the ones Ha Tang finds in the content.
  • Check links reports links that are empty, only #, on a placeholder domain (example.com, yourdomain.com, localhost…), not http(s), unreachable, or answering with an error page. Link problems hold back publishing until you choose Publish anyway.
  • Send test to your own address, Duplicate and Publish.

Only a published version can be sent. You can keep editing the draft: sends keep using the published version until you publish again. The list shows Unpublished changes when the draft differs from what is published.

Variables​

Write variables as {{{NAME}}}, or {{{NAME|default}}} with an inline default:

<p>Hi {{{NAME|there}}}, order {{{ORDER}}} for {{{TOTAL}}} VND is confirmed.</p>
  • Keys use letters, digits and _, up to 50 characters. A template declares at most 50 variables, and each value is at most 2,000 characters.
  • Values are HTML-escaped when they go into the HTML part.
  • A number variable refuses values that are not numbers.
  • The value comes from the send; if there is none, from the inline default; if there is none, from the declared fallback. A variable with none of these makes the send fail with 422 and nothing is sent.
  • Publishing fails while the content uses a variable that is not declared.
  • These names are reserved and filled for each recipient by broadcasts and automations: {{{FIRST_NAME}}}, {{{LAST_NAME}}}, {{{EMAIL}}}, {{{UNSUBSCRIBE_URL}}} (and its alias {{{RESEND_UNSUBSCRIBE_URL}}}). Contact properties are available as {{{contact.plan}}}; see Contacts, segments and topics. You do not declare these.

Send with a template​

curl -X POST https://api.hatang.dev/emails \
-H "Authorization: Bearer $HATANG_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": ["[email protected]"],
"template": {
"id": "order-confirmation",
"variables": { "NAME": "Lan", "ORDER": "DH1024", "TOTAL": 450000 }
}
}'
  • template.id is the template id (tpl_…) or its alias.
  • from, subject and reply_to in the request override the template's defaults. They are required when the template has none.
  • Do not send html or text together with template.
  • POST /emails/batch accepts template in each item.
  • To start a broadcast from a template, pass template_id to POST /broadcasts, or choose Start from a template in the broadcast editor. See Broadcasts.
ErrorCause
404 not_foundNo template has this id or alias.
422 validation_error "is not published yet"Publish the template first.
422 validation_error "Missing value for template variable"A variable has no value, no inline default and no fallback.
422 validation_error "The template has no from"Pass from in the request or set it on the template.

Manage templates with the API​

curl -X POST https://api.hatang.dev/templates \
-H "Authorization: Bearer $HATANG_API_KEY" -H "Content-Type: application/json" \
-d '{
"name": "Order confirmation",
"alias": "order-confirmation",
"from": "Acme <[email protected]>",
"subject": "Order {{{ORDER}}} is confirmed",
"html": "<p>Hi {{{NAME|there}}}, order {{{ORDER}}} for {{{TOTAL}}} VND is confirmed.</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_…" }
EndpointDescription
POST /templatesCreate a draft: name, html (required), alias, from, subject, reply_to, text, variables, folder.
GET /templatesList templates. Filters: q (name or alias), folder, status (draft or published), plus limit and after.
GET /templates/{id or alias}One template, with status, current_version_id, published_at and has_unpublished_versions.
PATCH /templates/{id or alias}Change the draft.
POST /templates/{id or alias}/publishPublish the draft.
POST /templates/{id or alias}/duplicateCopy it into a new draft named "(copy)".
DELETE /templates/{id or alias}Delete it.

An alias uses lowercase letters, digits, - and _, up to 64 characters, and is unique in your business. The Node.js SDK has the same calls under hatang.templates: create, get, list, update, publish, duplicate and remove.

Next steps​

View this page as Markdown