Skip to main content
explains the draft/publish model.
Manage templates over the API so they live in code and move through Git review. Each carries an nt_ ID and a draft/published lifecycle.

Prerequisites

Create a template

returns a new template in the DRAFT state:

Content needs a channel to live in

Every element belongs inside a channel block. Content whose elements sit at the top level is rejected at creation:
The channel block is what the renders when someone opens the template, so content without one is stored but opens as an empty document. A meta element may sit at the top level alongside the channel blocks. A template with no elements at all is fine: it is one nobody has written yet. Only creation is checked. Templates already saved without a channel block still send, and are left alone.

Read a template

returns the template, defaulting to the published version. Pass ?version=draft (or a version like v001) to read another:

Update content: the round-trip contract

Template content is read and written through a separate content endpoint. returns one of two shapes: the modern V2 elemental form ({ version, elements }, where every element carries a read-only checksum and a translated element carries its translations in locales) or the legacy V1 form ({ blocks, channels, checksum }).
PUT accepts V2 elemental only, and it replaces all content.
takes the { version, elements } tree inside a content object. Read the draft with ?version=draft, change the elements, and remove every checksum at any depth, because the write rejects them. Templates translated in Design Studio also carry keys starting with an underscore, such as _sourceHash, inside locales. Remove those too. Keep each element’s id and locales: an element sent without an id gets a new one, and one sent without locales loses its translations.
This example writes content to a template with no translations yet. To change only a template’s translations, write one locale at a time with , which leaves the default content and other locales as they are. See .

Publish

A PUT writes the draft. makes it the active version. You can also publish a historical version to roll back.

Aliases

An alias is a name you choose that stands in for a template’s nt_ ID on a send. Your code keeps a readable reference while the template behind it changes. You assign one in the template’s settings, under Alias, not over the API. has the rules and an example.

Read a template’s metrics

returns one template’s sends, deliveries, opens, clicks, errors, and undeliverables over time, broken out per provider and channel. covers the window, granularity, and plan caps.

Preview a template on email clients

renders a template’s email on real clients and returns a screenshot of each. covers device sets, timing, and reading the results.

Approval workflow

If your team gates publishing behind review, enable the approval workflow. Submitting a draft for review happens in the console, which puts the template in a read-only submission state. Over the API you then manage the submission’s checks: read them with , resolve or fail them with PUT, and cancel the submission with DELETE. Creating the submission itself happens in the console.

Manage Templates as code

1

Export a template to Elemental

is the JSON format Courier uses for template content, so it is what you version-control. Read a template’s content with and commit the { version, elements } JSON to your repo as the source of truth for the template.
2

Version-control the content

With the Elemental JSON in your repo, review template changes in a pull request like any other code. Apply an approved change back to Courier with . Remove the read-only checksum fields and any locales key that starts with an underscore, and keep each element’s id and locales before you PUT, and see the round-trip contract for the rest.
3

Manage templates from the CLI

The Courier CLI maps to the same template operations, so you can script create, update, publish, and version listing in CI:
The full verb set is list, create, retrieve, replace, archive, list-versions, publish, duplicate, retrieve-content, put-content, put-element, and put-locale.
4

Manage templates from an AI agent

The same operations are available as Courier tools (create_notification, put_notification_content, publish_notification, list_notification_versions), so an AI agent can create and update templates in your workspace. Connect the MCP server once and drive template changes from your agent.
5

Verify the round-trip

Export a template, change a value in the JSON, write it back with put-content, and publish. Confirm the change renders in a test send, then run list-versions and confirm your publish created a new version.

Endpoints

Every operation on a workspace Template. Names and reference links are generated from the OpenAPI spec, so this table can’t drift from what the API serves.

Response codes

These come up while working with this API and each is documented once, elsewhere:
  • Filling variables at send time. Pass data on the send and the Template resolves it. covers the syntax, scope, and the helpers.
  • Raw HTML for email. covers sending a full HTML document and what a provider does with it.
  • Workspace against Tenant Templates. These endpoints reach workspace Templates only. A Tenant’s own Templates live under /tenants/{tenant_id}/templates and are documented in .

Verify

Retrieve the template without a version parameter and confirm your published change is live, then send it to a test recipient and confirm it renders in .