Sending with templates
A template is stored email content you send by ID. Instead of inlining the
subject and body on every POST /v1/email, you reference a template and let
Anypost supply them.
How templates work
A template has a name, a subject, and a body. It also has a lifecycle
worth understanding before you create one.
Every template keeps two slots: a published version and an optional draft. Sends always use the published version. Edits land in the draft and change nothing until you publish them. A newly created template has only a draft, so it has no sendable content until its first publish.
This means a template is only usable for sending once it has been published at least once, and editing a live template never disturbs mail already going out under it.
Authoring format
A template body is authored one of two ways, set by its kind when you
create the template:
markdown, the recommended format. You write the body in emailmd, a markdown dialect built for email. A few lines of markdown compile to a responsive, well-styled message, with no HTML boilerplate to write or maintain. The dashboard's markdown editor includes an AI assistant that drafts and revises emailmd from a plain description.html, a raw HTML body. Use it when you need full control of the markup, or are bringing an existing HTML design across.
kind is fixed when the template is created and cannot be changed later. To
switch formats, create a new template.
Whichever format you pick, the plain-text body is derived automatically:
Anypost generates a plain-text alternative so recipients whose mail client
cannot render HTML still get a readable message. You never supply text
yourself.
Create a template
Create a template in the dashboard, or with POST /v1/templates:
curl https://api.anypost.com/v1/templates \
-H "Authorization: Bearer $ANYPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Welcome email",
"kind": "markdown",
"subject": "Welcome to Acme, {{first_name}}",
"markdown": "# Welcome\n\nHi {{first_name}}, your account is ready."
}'For a raw-HTML template, pass "kind": "html" with an html body instead.
The name must be unique within your team. The {{first_name}} placeholders
are optional; see Personalize with placeholders
below.
The response is the new template:
{
"id": "template_550e8400-e29b-41d4-a716-446655440000",
"name": "Welcome email",
"kind": "markdown",
"has_draft": true,
"published_at": null
}The subject and body you supplied were stored as the template's draft.
published_at is null, so the template cannot be used to send yet. Publish
it first.
Publish a template
Publishing promotes the draft into the published slot:
curl -X POST https://api.anypost.com/v1/templates/template_550e8400.../publish \
-H "Authorization: Bearer $ANYPOST_API_KEY"The response shows published_at set and has_draft back to false. The
template is now sendable. A template with no draft to publish returns 422.
Send with a template
Send with a template by passing template_id to POST /v1/email in place of
a body:
curl https://api.anypost.com/v1/email \
-H "Authorization: Bearer $ANYPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "Acme <[email protected]>",
"to": ["[email protected]"],
"template_id": "template_550e8400-e29b-41d4-a716-446655440000",
"variables": { "first_name": "Alex" }
}'The subject and both body parts come from the template's published content. The response and behavior are otherwise identical to any other send; see Send a single email.
Two rules govern a templated send:
- A template send carries no inline body.
template_idcannot be combined withtextorhtml. A request with both is rejected with422: a send has one body source, not two. subjectis optional, and overrides the template. Omit it and the template's subject is used. Supply it and your value wins for that send, which is how you vary the subject without forking the template.
Personalize with placeholders
A template body and subject can contain {{ placeholder }} markers. Pass a
variables object on the send and Anypost substitutes the values before
delivery, so one template serves many recipients.
"variables": { "first_name": "Alex", "plan": "Pro" }A send with no variables is delivered exactly as stored, with no
substitution, so a template whose literal text happens to contain {{ }} is
never mangled. Placeholder syntax, nesting, and the size limits are covered
in Variables & personalization.
Edit a published template
Editing is a two-step cycle: update the draft, then publish it.
curl -X PATCH https://api.anypost.com/v1/templates/template_550e8400.../draft \
-H "Authorization: Bearer $ANYPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"subject": "Welcome aboard, {{first_name}}",
"markdown": "# Welcome aboard\n\nHi {{first_name}}, welcome to Acme."
}'This creates the draft if there is none and updates it otherwise. The
published version is untouched, so sends keep using the old content until you
run POST /v1/templates/{id}/publish again. Discard a draft you do not want
with DELETE /v1/templates/{id}/draft.
To rename a template, PATCH /v1/templates/{id} with a new name. Body
content cannot be changed on that path: it is draft-versioned, and the draft
endpoint is the only way to change it.
Managing templates
| Operation | Endpoint |
|---|---|
| List templates | GET /v1/templates |
| Retrieve one | GET /v1/templates/{id} |
| View the draft | GET /v1/templates/{id}/draft |
| Duplicate | POST /v1/templates/{id}/duplicate |
| Rename | PATCH /v1/templates/{id} |
| Delete | DELETE /v1/templates/{id} |
A duplicate starts as a new, unpublished template seeded from the source's content, so it must be published before use. A team may hold up to 500 templates.
When a templated send fails
A send that references a template can fail validation before any mail is
queued. Each returns 400 with a validation_error; see
API conventions for the error shape.
| Problem | Cause |
|---|---|
| Template not found | No template with that ID exists for your team. |
| Template has no published content | The template exists but was never published. Publish a draft first. |
subject is required | Neither the request nor the template supplied a subject. |
Where to go next
- Variables & personalization: placeholder syntax and per-recipient values.
- Batch sending: send one template to many recipients in a single request.
- Send a single email: the full
POST /v1/emailrequest.