Skip to main content

Documentation Index

Fetch the complete documentation index at: https://www.courier.com/docs/llms.txt

Use this file to discover all available pages before exploring further.

The Courier CLI and MCP server both wrap the Notification Templates REST API. The CLI runs as a native binary in your terminal; MCP lets your IDE agent (Cursor, VS Code Copilot, Claude Code, etc.) call Courier tools on your behalf. Both the CLI and MCP server cover the full template lifecycle: create, inspect, update, publish, send, version history, and archive. Every step in this tutorial shows both approaches side by side so you can pick the one that fits your workflow. By the end you will have created a draft template with Elemental content, published it, verified the published body, sent a test message, checked version history, and archived the template when you’re done.
This tutorial covers workspace-level notification templates (/notifications). For tenant-scoped templates used with the embeddable Courier Create editor, see How to Use the Courier Create API.

Prerequisites

Export your key (the CLI reads it automatically; MCP reads it from your server config):
export COURIER_API_KEY="your-api-key"

Step 1 - List existing templates

Start by seeing what is already on your workspace.
courier notifications list
The response includes a results array of templates and a paging object. Note the id of any template you want to inspect further. Courier template ids look like nt_....

Step 2 - Create a draft template

Create a new notification template with Elemental content. The example builds a shipping-update email with a subject line, a text block, and a call-to-action button.
courier notifications create \
  --state DRAFT \
  --notification '{
    "name": "Shipping Update",
    "tags": [],
    "brand": null,
    "subscription": null,
    "routing": { "strategy_id": "YOUR_STRATEGY_ID" },
    "content": {
      "version": "2022-01-01",
      "elements": [
        { "type": "meta", "title": "Your order {{order_id}} has shipped" },
        {
          "type": "text",
          "content": "Hi {{name}}, your package is on the way. Tracking number: {{tracking_url}}."
        },
        {
          "type": "action",
          "content": "Track shipment",
          "href": "{{tracking_url}}"
        }
      ]
    }
  }'
The response contains an id field. Save this as your TEMPLATE_ID.
export TEMPLATE_ID="nt_..."
Where does strategy_id come from? Every template needs a routing strategy that defines which channels to use and in what order. You can list existing strategies with courier routing-strategies list or grab one from an existing template in Studio. See How to Use the Templates API for a full walkthrough.

Step 3 - Inspect the draft

Verify the draft content before publishing. Use retrieve-content --version draft on the CLI; the MCP server has a dedicated get_notification_draft_content tool.
courier notifications retrieve-content --id $TEMPLATE_ID --version draft
The response shows your Elemental blocks exactly as stored. If anything looks wrong, you can replace the content in Step 4 before publishing.

Step 4 - Update the content (optional)

Need to tweak the draft? Use put-content to replace just the Elemental content without touching the template’s name, routing, or other metadata.
courier notifications put-content --id $TEMPLATE_ID \
  --state DRAFT \
  --content '{
    "version": "2022-01-01",
    "elements": [
      { "type": "meta", "title": "Order {{order_id}} - Shipped!" },
      {
        "type": "text",
        "content": "Good news, {{name}}! Your package shipped today and should arrive by {{eta}}."
      },
      {
        "type": "action",
        "content": "Track your package",
        "href": "{{tracking_url}}"
      }
    ]
  }'
To replace the entire template (name, routing, content, and all), use courier notifications replace --id $TEMPLATE_ID --notification '{...}' instead. That’s a full overwrite; include every field you want to keep.

Step 5 - Publish

Make the current draft live. Recipients will see this version the next time you send.
courier notifications publish --id $TEMPLATE_ID

Step 6 - Verify the published content

Read back the live version to confirm what recipients will see.
courier notifications retrieve-content --id $TEMPLATE_ID
retrieve-content defaults to the published version. Add --version draft to see the draft. After a publish they will match, but they can differ if you edit the draft without publishing again.

Step 7 - Send a test message

Fire a notification using your template. The data fields must match the {{variables}} in your Elemental content.
courier send message --message '{
  "template": "'"$TEMPLATE_ID"'",
  "to": { "email": "you@example.com" },
  "data": {
    "order_id": "ORD-42",
    "name": "Alex",
    "eta": "May 15",
    "tracking_url": "https://example.com/track/ORD-42"
  }
}'
The response returns a requestId. Check delivery status in Message Logs or by calling courier messages list.

Step 8 - Check version history

See every published version of the template.
courier notifications list-versions --id $TEMPLATE_ID
Each version has a created_at timestamp and a version string you can use to inspect or publish a specific historical snapshot.

Step 9 - Archive the template

When a template is no longer needed, archive it. Archived templates stop delivering but are not permanently deleted.
courier notifications archive --id $TEMPLATE_ID

CLI and MCP coverage

StepCLIMCPcURL
List templatesnotifications listlist_notificationsGET /notifications
Createnotifications createcreate_notificationPOST /notifications
Read draftnotifications retrieve-content --version draftget_notification_draft_contentGET /notifications/{id}/draft/content
Update contentnotifications put-contentput_notification_contentPUT /notifications/{id}/draft/content
Publishnotifications publishpublish_notificationPOST /notifications/{id}/publish
Read publishednotifications retrieve-contentget_notification_contentGET /notifications/{id}/content
Sendsend messagesend_message_templatePOST /send
Versionsnotifications list-versionslist_notification_versionsGET /notifications/{id}/versions
Archivenotifications archivearchive_notificationDELETE /notifications/{id}

Tips for CI / automation

  • Idempotent updates: Use courier notifications replace --id nt_... (or PUT /notifications/{id}) to overwrite a template by id, making deploys repeatable.
  • JSON output: Add --format json to any CLI command for machine-parseable output; pipe through jq for filtering.
  • Dry runs with test keys: Use a Test environment API key to iterate without sending real notifications.
  • MCP in CI: The MCP server can be called from any MCP-compatible runtime, not just IDEs. Use it in custom automation scripts that support the Model Context Protocol.

What’s Next

CLI reference

Full command list, flags, and recipes

MCP server

All MCP tools and IDE setup

Templates API reference

Endpoint details and content schema

Templates API tutorial

Same workflow with curl, Node.js, and Python SDK examples