Skip to main content
Create, update, publish, and manage notification templates over the /notifications API. A template holds Elemental content for one or more channels plus reusable routing, the same assets you edit in Design Studio. Every template has a draft and a published version: writes land on the draft, sends use the published version.
The Templates API tutorial walks through create, publish, and send end-to-end with working code.

Endpoints

All paths are rooted at https://api.courier.com. Authenticate every request with your workspace API key as a Bearer token: Authorization: Bearer <token>.
POST /notifications and PUT /notifications/{id} work with Elemental templates, the ones built in Design Studio. They do not accept older Classic (V1) templates. GET /notifications returns both kinds in one list, so check each row before assuming a uniform shape.

Create a template

Send POST /notifications with a notification object and an optional state flag (defaults to DRAFT). Set COURIER_API_KEY in your environment first.
The notification object has a few parts you’ll set most often:
  • name (required) and tags (required, an array; pass [] if you have none). Include brand and subscription as well: they may be null, but the keys must be present or the request is rejected.
  • routing: which channels and providers to use. Pass null to skip it for now, or { "strategy_id": "rs_..." } to attach an existing strategy.
  • content: the template body in Elemental, a version plus an elements array of channel elements, one per channel. Each channel element holds that channel’s blocks, so one template carries email, SMS, push, and more. Courier renders the matching channel for each delivery (see Author content that stays editable).
To make a create retry-safe, pass an Idempotency-Key header. Courier returns the stored response instead of creating a second template.

Edit the draft

PUT /notifications/{id}/content writes the draft body. Send the Elemental document nested under a content key, which differs from POST /notifications, where content sits inside notification.
This replaces the entire draft body rather than patching it. Any channel or block you leave out of the request is dropped, so read the current content first if you only mean to change part of it.

Publish, read, and archive

Publishing promotes the draft to what recipients see. Until you publish, a template created with state: "DRAFT" is invisible to sends.
  • Publish: POST /notifications/{id}/publish promotes the current draft to live and returns 204 with no body. Pass a version to publish a specific earlier version instead.
  • Read: GET /notifications/{id}/content returns the published body. Pass ?version=draft for the draft, or ?version=v001 for a specific version. Compare draft against published to see what is unpublished.
  • History: GET /notifications/{id}/versions lists published versions, most recent first, for auditing or rollback.
  • Replace: PUT /notifications/{id} replaces the whole template, including name, routing, and settings, not just the body.
  • Archive: DELETE /notifications/{id} archives the template so it drops out of the normal catalog. Check what still references it before you archive.

Author content that stays editable

Give each channel its own channel element at the top level, as in the example above. This is how Design Studio stores templates, so a template you create through the API stays editable there.
Blocks placed at the top level, outside a channel element, send correctly but may not appear as editable blocks in Design Studio. This is the most common way an API-created template ends up locked to the API.
For colored or bold runs within a paragraph, use a text element’s inline elements array (string/link nodes) or Markdown (**bold**) in content. To set a color across a whole template, use a brand.

Fill variables at send time

Variables in your template resolve against the data object on the send call. The {{order_id}}, {{name}}, and {{tracking_url}} placeholders in the examples above come from here:
cURL
Courier also resolves profile., tenant., and brand. prefixes against the recipient’s stored profile, their tenant, and the brand. A name with no prefix is looked up in data, so {{order_id}} and {{data.order_id}} reach the same value.
Elemental content uses double braces, as in the examples above. The single-brace form ({order_id}) is what you type into block fields in Design Studio. Same data either way, different authoring surface.
See Inserting variables for the full context, and Send a message for the rest of the send payload.

Add raw HTML (email only)

Raw HTML applies to the email channel only; other channels use blocks or their own raw payload. To author an email as HTML instead of blocks, for example when porting a legacy template, put a complete HTML document on the email channel node’s raw.html with the handlebars transformer. Keep a meta block for the subject, since raw.html has none.

Response codes

Approval submissions

When a workspace uses the template approval workflow, review state attaches to a submission rather than the template. The operations live on /notifications/{id}/{submissionId}/checks: read the checks, replace them, or cancel the submission.

Workspace templates vs tenant templates

Everything on this page is scoped to your workspace: one template list per Courier account, matching what you see in Studio, on untenanted /notifications/... paths. If you manage a separate set of templates per tenant, those live on /tenants/{tenant_id}/templates/... instead. See the Courier Create API.