Skip to main content

Templates

A template is reusable content with variables. Sending with template_id keeps the copy out of your codebase, so it can be changed without a deploy.

The part worth understanding is versioning, because it is what stops an edit from changing mail that is already in flight.

Drafts and versions

Every template has two things:

  • A draft. Mutable. This is what PATCH /v1/templates/{id} writes and what the dashboard editor saves. Nothing sends from the draft.
  • Versions. Immutable snapshots, numbered from 1. One of them is the published version, and that is what a send uses.

Editing a template is therefore safe by construction. You can rewrite the draft as often as you like and production keeps sending the published version until you say otherwise.

Create one

curl https://api.epostix.com/v1/templates \
-H "Authorization: Bearer $EPOSTIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "welcome",
"subject": "Welcome {{ name }}",
"html": "<h1>Hi {{ name }}</h1>"
}'

That creates the template and publishes version 1 in one call. Pass "publish": false to create a draft without publishing anything.

Send with it

{
"from": "[email protected]",
"to": ["[email protected]"],
"template_id": "cabca13e-...",
"template_data": {"name": "Alex"}
}

template_id is mutually exclusive with html and text. Sending both is a validation_error, because there would be no way to know which you meant.

The response carries the template_version that was used, so a message can always be traced back to the exact content it was rendered from.

Publish a change

# 1. edit the draft, which does not affect sending
curl -X PATCH https://api.epostix.com/v1/templates/{id} \
-H "Authorization: Bearer $EPOSTIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"html": "<h1>Welcome aboard, {{ name }}</h1>"}'

# 2. freeze it as a new version and publish it
curl -X POST https://api.epostix.com/v1/templates/{id}/versions \
-H "Authorization: Bearer $EPOSTIX_API_KEY"

Pass {"publish": false} on step 2 to record the version without switching sends to it. That is how you stage content ahead of a release.

Roll back

curl -X POST https://api.epostix.com/v1/templates/{id}/publish \
-H "Authorization: Bearer $EPOSTIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"version": 1}'

Instant, and it changes nothing about the content. Versions are immutable, so rolling forward again is another publish.

Pin a version for a safe deploy

{"template_id": "...", "template_version": 3, "template_data": {...}}

Pinning is how you decouple a content change from a code change. Your release names the version it was tested against, so publishing a new one cannot alter what that release sends.

A template with no published version returns template_render_failed rather than silently falling back to the newest one.

Check a template before you send

curl https://api.epostix.com/v1/templates/render \
-H "Authorization: Bearer $EPOSTIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"template_id": "...", "data": {"name": "Alex"}}'

This renders and returns the result without sending anything. missing_variables lists the variables the template uses that have no default and were not supplied, which is the fastest way to find a {{ name }} that will render blank.

Archiving

DELETE archives rather than destroys. Past messages stay explicable, and the template can no longer be sent with.