Docs/API reference

Templates API

Manage reusable email templates stored per team.

Every request needs a bearer token and goes to a path under https://api.anypost.com/v1. See API conventions for the shared request, error, and pagination rules.

List templates

GET /v1/templates

Returns the authenticated team's templates, newest-first, with cursor pagination.

Parameters

limitintegerin query[optional]

Number of items to return.

afterstringin query[optional]

Opaque cursor from a previous response's next_cursor. Do not parse.

Example request

curl https://api.anypost.com/v1/templates \
  -H "Authorization: Bearer $ANYPOST_API_KEY"

Response body

On success (200), the response body is:

dataarray of Template
has_moreboolean
next_cursorstring

May be null.

{
  "data": [
    {
      "id": "template_550e8400-e29b-41d4-a716-446655440000",
      "name": "Welcome email",
      "subject": "Welcome to Anypost!",
      "kind": "html",
      "html": "string",
      "text": "string",
      "markdown": "string",
      "has_draft": true,
      "published_at": "string",
      "created_at": "string",
      "updated_at": "string"
    }
  ],
  "has_more": true,
  "next_cursor": "string"
}

Responses

StatusDescription
200Paginated list of templates.
401Missing or invalid credentials.

Create a template

POST /v1/templates

Creates a new template for the authenticated team. name is required and must be unique within the team. kind defaults to html and is immutable thereafter: an html template supplies an html body, a markdown template supplies a markdown source. The plain-text body is always derived server-side and is never accepted as input. The new template starts unpublished — publish it before sending. Each team is capped at 500 templates; exceeding it returns 422 validation_error.

Request body

Send as JSON with Content-Type: application/json.

namestring[required]
subjectstring[optional]

May be null.

kindstring[optional]

Defaults to html if omitted. Immutable once the template exists.

One of: html, markdown.

htmlstring[optional]

May be null.

markdownstring[optional]

emailmd source. Required when kind=markdown; rejected when kind=html.

May be null.

Example request

curl https://api.anypost.com/v1/templates \
  -X POST \
  -H "Authorization: Bearer $ANYPOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Welcome email"
  }'

Response body

On success (201), the response body is:

idstring
namestring

Identifier for the template, unique within the team.

subjectstring

Published default subject line. null until the template is first published.

May be null.

kindstring

Authoring format. html templates author a raw html body; the text body is derived from it automatically. markdown templates store an emailmd source document in markdown; html and text are server-rendered on save. Both kinds expose html/text for read. Immutable once a template exists.

One of: html, markdown.

htmlstring

Published HTML body. Up to 256 KB (262 144 bytes). null until the template is first published.

May be null.

textstring

Published plain-text body, up to 64 KB (65 536 bytes). Always machine-derived — from the html body for kind=html, or rendered for kind=markdown — and never set directly. null until the template is first published.

May be null.

markdownstring

Published emailmd markdown source. Only set when kind=markdown; null for kind=html or until the template is first published.

May be null.

has_draftboolean

Whether the template has an unpublished draft pending. Fetch the draft content from /templates/{id}/draft.

published_atstring (date-time)

When the template was last published. null if it has never been published — such a template holds no sendable content.

May be null.

created_atstring (date-time)
updated_atstring (date-time)
{
  "id": "template_550e8400-e29b-41d4-a716-446655440000",
  "name": "Welcome email",
  "subject": "Welcome to Anypost!",
  "kind": "html",
  "html": "string",
  "text": "string",
  "markdown": "string",
  "has_draft": true,
  "published_at": "string",
  "created_at": "string",
  "updated_at": "string"
}

Responses

StatusDescription
201Template created.
401Missing or invalid credentials.
413Request body exceeded the 5 MB gateway limit. Rejected at the transport layer before authentication or validation, so the response uses a shorter error shape than application-layer errors. The connection is closed after the response.
422Request validation failed.

Retrieve a template

GET /v1/templates/{id}

Parameters

idstringin path[required]

Example request

curl https://api.anypost.com/v1/templates/template_550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer $ANYPOST_API_KEY"

Response body

On success (200), the response body is:

idstring
namestring

Identifier for the template, unique within the team.

subjectstring

Published default subject line. null until the template is first published.

May be null.

kindstring

Authoring format. html templates author a raw html body; the text body is derived from it automatically. markdown templates store an emailmd source document in markdown; html and text are server-rendered on save. Both kinds expose html/text for read. Immutable once a template exists.

One of: html, markdown.

htmlstring

Published HTML body. Up to 256 KB (262 144 bytes). null until the template is first published.

May be null.

textstring

Published plain-text body, up to 64 KB (65 536 bytes). Always machine-derived — from the html body for kind=html, or rendered for kind=markdown — and never set directly. null until the template is first published.

May be null.

markdownstring

Published emailmd markdown source. Only set when kind=markdown; null for kind=html or until the template is first published.

May be null.

has_draftboolean

Whether the template has an unpublished draft pending. Fetch the draft content from /templates/{id}/draft.

published_atstring (date-time)

When the template was last published. null if it has never been published — such a template holds no sendable content.

May be null.

created_atstring (date-time)
updated_atstring (date-time)
{
  "id": "template_550e8400-e29b-41d4-a716-446655440000",
  "name": "Welcome email",
  "subject": "Welcome to Anypost!",
  "kind": "html",
  "html": "string",
  "text": "string",
  "markdown": "string",
  "has_draft": true,
  "published_at": "string",
  "created_at": "string",
  "updated_at": "string"
}

Responses

StatusDescription
200The template.
404Resource not found.

Update template metadata

PATCH /v1/templates/{id}

Updates the template's name. Body content is draft-versioned — subject, html, text, markdown (and kind) are rejected here; use PATCH /templates/{id}/draft instead.

Parameters

idstringin path[required]

Request body

Send as JSON with Content-Type: application/json.

namestring[optional]

Example request

curl https://api.anypost.com/v1/templates/template_550e8400-e29b-41d4-a716-446655440000 \
  -X PATCH \
  -H "Authorization: Bearer $ANYPOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response body

On success (200), the response body is:

idstring
namestring

Identifier for the template, unique within the team.

subjectstring

Published default subject line. null until the template is first published.

May be null.

kindstring

Authoring format. html templates author a raw html body; the text body is derived from it automatically. markdown templates store an emailmd source document in markdown; html and text are server-rendered on save. Both kinds expose html/text for read. Immutable once a template exists.

One of: html, markdown.

htmlstring

Published HTML body. Up to 256 KB (262 144 bytes). null until the template is first published.

May be null.

textstring

Published plain-text body, up to 64 KB (65 536 bytes). Always machine-derived — from the html body for kind=html, or rendered for kind=markdown — and never set directly. null until the template is first published.

May be null.

markdownstring

Published emailmd markdown source. Only set when kind=markdown; null for kind=html or until the template is first published.

May be null.

has_draftboolean

Whether the template has an unpublished draft pending. Fetch the draft content from /templates/{id}/draft.

published_atstring (date-time)

When the template was last published. null if it has never been published — such a template holds no sendable content.

May be null.

created_atstring (date-time)
updated_atstring (date-time)
{
  "id": "template_550e8400-e29b-41d4-a716-446655440000",
  "name": "Welcome email",
  "subject": "Welcome to Anypost!",
  "kind": "html",
  "html": "string",
  "text": "string",
  "markdown": "string",
  "has_draft": true,
  "published_at": "string",
  "created_at": "string",
  "updated_at": "string"
}

Responses

StatusDescription
200The updated template.
401Missing or invalid credentials.
404Resource not found.
422Request validation failed.

Delete a template

DELETE /v1/templates/{id}

Deletes the template and its draft, if any.

Parameters

idstringin path[required]

Example request

curl https://api.anypost.com/v1/templates/template_550e8400-e29b-41d4-a716-446655440000 \
  -X DELETE \
  -H "Authorization: Bearer $ANYPOST_API_KEY"

Responses

StatusDescription
204Deleted.
404Resource not found.

Duplicate a template

POST /v1/templates/{id}/duplicate

Creates a copy of the template. The copy is a brand-new template that starts unpublished, with a draft seeded from the source's current editable content — the source's draft if it has one, otherwise its published content. The copy must be published before it can be used for sending.

name is optional: when omitted the server names the copy "<source name> (copy)" (disambiguated with (copy 2), (copy 3), … when needed). When supplied it must be unique within the team. The per-team 500-template cap applies — exceeding it returns 422 validation_error.

Parameters

idstringin path[required]

Request body

Send as JSON with Content-Type: application/json.

namestring[optional]

Name for the copy. Defaults to "<source name> (copy)" when omitted.

Example request

curl https://api.anypost.com/v1/templates/template_550e8400-e29b-41d4-a716-446655440000/duplicate \
  -X POST \
  -H "Authorization: Bearer $ANYPOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response body

On success (201), the response body is:

idstring
namestring

Identifier for the template, unique within the team.

subjectstring

Published default subject line. null until the template is first published.

May be null.

kindstring

Authoring format. html templates author a raw html body; the text body is derived from it automatically. markdown templates store an emailmd source document in markdown; html and text are server-rendered on save. Both kinds expose html/text for read. Immutable once a template exists.

One of: html, markdown.

htmlstring

Published HTML body. Up to 256 KB (262 144 bytes). null until the template is first published.

May be null.

textstring

Published plain-text body, up to 64 KB (65 536 bytes). Always machine-derived — from the html body for kind=html, or rendered for kind=markdown — and never set directly. null until the template is first published.

May be null.

markdownstring

Published emailmd markdown source. Only set when kind=markdown; null for kind=html or until the template is first published.

May be null.

has_draftboolean

Whether the template has an unpublished draft pending. Fetch the draft content from /templates/{id}/draft.

published_atstring (date-time)

When the template was last published. null if it has never been published — such a template holds no sendable content.

May be null.

created_atstring (date-time)
updated_atstring (date-time)
{
  "id": "template_550e8400-e29b-41d4-a716-446655440000",
  "name": "Welcome email",
  "subject": "Welcome to Anypost!",
  "kind": "html",
  "html": "string",
  "text": "string",
  "markdown": "string",
  "has_draft": true,
  "published_at": "string",
  "created_at": "string",
  "updated_at": "string"
}

Responses

StatusDescription
201The duplicated template.
401Missing or invalid credentials.
404Resource not found.
422Request validation failed.

Retrieve the template draft

GET /v1/templates/{id}/draft

Returns the template's unpublished draft content.

Parameters

idstringin path[required]

Example request

curl https://api.anypost.com/v1/templates/template_550e8400-e29b-41d4-a716-446655440000/draft \
  -H "Authorization: Bearer $ANYPOST_API_KEY"

Response body

On success (200), the response body is:

subjectstring

May be null.

htmlstring

May be null.

textstring

Draft plain-text body. Always machine-derived from the draft's html/markdown; never set directly.

May be null.

markdownstring

May be null.

updated_atstring (date-time)
{
  "subject": "string",
  "html": "string",
  "text": "string",
  "markdown": "string",
  "updated_at": "string"
}

Responses

StatusDescription
200The draft content.
404Resource not found.

Create or update the template draft

PATCH /v1/templates/{id}/draft

Idempotent upsert of the template's draft. Creates the draft if none exists, otherwise updates it. The published content is untouched until the draft is published. Always responds 200.

Parameters

idstringin path[required]

Request body

Send as JSON with Content-Type: application/json.

subjectstring[optional]

May be null.

htmlstring[optional]

May be null.

markdownstring[optional]

May be null.

Example request

curl https://api.anypost.com/v1/templates/template_550e8400-e29b-41d4-a716-446655440000/draft \
  -X PATCH \
  -H "Authorization: Bearer $ANYPOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Response body

On success (200), the response body is:

subjectstring

May be null.

htmlstring

May be null.

textstring

Draft plain-text body. Always machine-derived from the draft's html/markdown; never set directly.

May be null.

markdownstring

May be null.

updated_atstring (date-time)
{
  "subject": "string",
  "html": "string",
  "text": "string",
  "markdown": "string",
  "updated_at": "string"
}

Responses

StatusDescription
200The saved draft.
401Missing or invalid credentials.
404Resource not found.
413Request body exceeded the 5 MB gateway limit. Rejected at the transport layer before authentication or validation, so the response uses a shorter error shape than application-layer errors. The connection is closed after the response.
422Request validation failed.

Discard the template draft

DELETE /v1/templates/{id}/draft

Deletes the template's draft without affecting the published content. Idempotent — succeeds even when no draft exists.

Parameters

idstringin path[required]

Example request

curl https://api.anypost.com/v1/templates/template_550e8400-e29b-41d4-a716-446655440000/draft \
  -X DELETE \
  -H "Authorization: Bearer $ANYPOST_API_KEY"

Responses

StatusDescription
204Draft discarded.
404Resource not found.

Publish the template draft

POST /v1/templates/{id}/publish

Promotes the template's draft into the published slot. The previous published content, if any, is overwritten — not archived. The draft is consumed: the template has no pending draft immediately after publishing.

Parameters

idstringin path[required]

Example request

curl https://api.anypost.com/v1/templates/template_550e8400-e29b-41d4-a716-446655440000/publish \
  -X POST \
  -H "Authorization: Bearer $ANYPOST_API_KEY"

Response body

On success (200), the response body is:

idstring
namestring

Identifier for the template, unique within the team.

subjectstring

Published default subject line. null until the template is first published.

May be null.

kindstring

Authoring format. html templates author a raw html body; the text body is derived from it automatically. markdown templates store an emailmd source document in markdown; html and text are server-rendered on save. Both kinds expose html/text for read. Immutable once a template exists.

One of: html, markdown.

htmlstring

Published HTML body. Up to 256 KB (262 144 bytes). null until the template is first published.

May be null.

textstring

Published plain-text body, up to 64 KB (65 536 bytes). Always machine-derived — from the html body for kind=html, or rendered for kind=markdown — and never set directly. null until the template is first published.

May be null.

markdownstring

Published emailmd markdown source. Only set when kind=markdown; null for kind=html or until the template is first published.

May be null.

has_draftboolean

Whether the template has an unpublished draft pending. Fetch the draft content from /templates/{id}/draft.

published_atstring (date-time)

When the template was last published. null if it has never been published — such a template holds no sendable content.

May be null.

created_atstring (date-time)
updated_atstring (date-time)
{
  "id": "template_550e8400-e29b-41d4-a716-446655440000",
  "name": "Welcome email",
  "subject": "Welcome to Anypost!",
  "kind": "html",
  "html": "string",
  "text": "string",
  "markdown": "string",
  "has_draft": true,
  "published_at": "string",
  "created_at": "string",
  "updated_at": "string"
}

Responses

StatusDescription
200The published template.
401Missing or invalid credentials.
404Resource not found.
422Request validation failed.