> ## 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.

# How to Manage Templates from the CLI and MCP

> Create, publish, update, and archive workspace notification templates using the Courier CLI and MCP server, without leaving your terminal or IDE.

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.

<Info>
  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](/tutorials/content/how-to-use-courier-create-api).
</Info>

## Prerequisites

* Courier [API key](/platform/workspaces/environments-api-keys)
* **CLI path:** Install the [Courier CLI](/tools/cli) (`npm i -g @trycourier/cli`)
* **MCP path:** Add the [Courier MCP server](/tools/mcp) to your IDE

Export your key (the CLI reads it automatically; MCP reads it from your server config):

```bash theme={null}
export COURIER_API_KEY="your-api-key"
```

## Step 1 - List existing templates

Start by seeing what is already on your workspace.

<CodeGroup>
  ```bash CLI icon="terminal" theme={null}
  courier notifications list
  ```

  ```text MCP icon="microchip-ai" theme={null}
  List my notification templates.
  ```

  ```bash cURL icon="code" theme={null}
  curl -s "https://api.courier.com/notifications" \
    -H "Authorization: Bearer $COURIER_API_KEY" | jq .
  ```
</CodeGroup>

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.

<CodeGroup>
  ```bash CLI icon="terminal" wrap theme={null}
  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}}"
          }
        ]
      }
    }'
  ```

  ```text MCP icon="microchip-ai" theme={null}
  Create a draft notification template called "Shipping Update"
  with routing strategy YOUR_STRATEGY_ID and Elemental content:
  - meta: "Your order {{order_id}} has shipped"
  - text: "Hi {{name}}, your package is on the way. Tracking number: {{tracking_url}}."
  - action: "Track shipment" linking to {{tracking_url}}
  ```

  ```bash cURL icon="code" wrap theme={null}
  curl -X POST "https://api.courier.com/notifications" \
    -H "Authorization: Bearer $COURIER_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "published": false,
      "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}}"
            }
          ]
        }
      }
    }'
  ```
</CodeGroup>

The response contains an `id` field. Save this as your `TEMPLATE_ID`.

```bash theme={null}
export TEMPLATE_ID="nt_..."
```

<Tip>
  **Where does `strategy_id` come from?** Every template needs a [routing strategy](/platform/content/template-designer/routing-configuration#managing-routing-strategies-with-the-rest-api) 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](/tutorials/content/how-to-use-templates-api#step-1b-get-or-create-a-routing-strategy) for a full walkthrough.
</Tip>

## 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.

<CodeGroup>
  ```bash CLI icon="terminal" theme={null}
  courier notifications retrieve-content --id $TEMPLATE_ID --version draft
  ```

  ```text MCP icon="microchip-ai" theme={null}
  Get the draft content for notification template nt_...
  ```

  ```bash cURL icon="code" theme={null}
  curl -s "https://api.courier.com/notifications/$TEMPLATE_ID/draft/content" \
    -H "Authorization: Bearer $COURIER_API_KEY" | jq .
  ```
</CodeGroup>

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.

<CodeGroup>
  ```bash CLI icon="terminal" wrap theme={null}
  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}}"
        }
      ]
    }'
  ```

  ```text MCP icon="microchip-ai" theme={null}
  Update the content for notification template TEMPLATE_ID:
  - meta: "Order {{order_id}} - Shipped!"
  - text: "Good news, {{name}}! Your package shipped today and should arrive by {{eta}}."
  - action: "Track your package" linking to {{tracking_url}}
  ```

  ```bash cURL icon="code" wrap theme={null}
  curl -X PUT "https://api.courier.com/notifications/$TEMPLATE_ID/draft/content" \
    -H "Authorization: Bearer $COURIER_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "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}}"
          }
        ]
      }
    }'
  ```
</CodeGroup>

<Tip>
  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.
</Tip>

## Step 5 - Publish

Make the current draft live. Recipients will see this version the next time you send.

<CodeGroup>
  ```bash CLI icon="terminal" theme={null}
  courier notifications publish --id $TEMPLATE_ID
  ```

  ```text MCP icon="microchip-ai" theme={null}
  Publish notification template TEMPLATE_ID.
  ```

  ```bash cURL icon="code" theme={null}
  curl -X POST "https://api.courier.com/notifications/$TEMPLATE_ID/publish" \
    -H "Authorization: Bearer $COURIER_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{}'
  ```
</CodeGroup>

## Step 6 - Verify the published content

Read back the live version to confirm what recipients will see.

<CodeGroup>
  ```bash CLI icon="terminal" theme={null}
  courier notifications retrieve-content --id $TEMPLATE_ID
  ```

  ```text MCP icon="microchip-ai" theme={null}
  Get the published content for notification template nt_...
  ```

  ```bash cURL icon="code" theme={null}
  curl -s "https://api.courier.com/notifications/$TEMPLATE_ID/content" \
    -H "Authorization: Bearer $COURIER_API_KEY" | jq .
  ```
</CodeGroup>

<Note>
  `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.
</Note>

## Step 7 - Send a test message

Fire a notification using your template. The `data` fields must match the `{{variables}}` in your Elemental content.

<CodeGroup>
  ```bash CLI icon="terminal" wrap theme={null}
  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"
    }
  }'
  ```

  ```text MCP icon="microchip-ai" theme={null}
  Send a message using template nt_... to user user_123
  with data: order_id "ORD-42", name "Alex", eta "May 15",
  tracking_url "https://example.com/track/ORD-42".
  ```

  ```bash cURL icon="code" wrap theme={null}
  curl -X POST "https://api.courier.com/send" \
    -H "Authorization: Bearer $COURIER_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "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"
        }
      }
    }'
  ```
</CodeGroup>

The response returns a `requestId`. Check delivery status in [Message Logs](/platform/analytics/message-logs) or by calling `courier messages list`.

## Step 8 - Check version history

See every published version of the template.

<CodeGroup>
  ```bash CLI icon="terminal" theme={null}
  courier notifications list-versions --id $TEMPLATE_ID
  ```

  ```text MCP icon="microchip-ai" theme={null}
  List the version history for notification template TEMPLATE_ID.
  ```

  ```bash cURL icon="code" theme={null}
  curl -s "https://api.courier.com/notifications/$TEMPLATE_ID/versions" \
    -H "Authorization: Bearer $COURIER_API_KEY" | jq .
  ```
</CodeGroup>

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.

<CodeGroup>
  ```bash CLI icon="terminal" theme={null}
  courier notifications archive --id $TEMPLATE_ID
  ```

  ```text MCP icon="microchip-ai" theme={null}
  Archive notification template TEMPLATE_ID.
  ```

  ```bash cURL icon="code" theme={null}
  curl -X DELETE "https://api.courier.com/notifications/$TEMPLATE_ID" \
    -H "Authorization: Bearer $COURIER_API_KEY"
  ```
</CodeGroup>

## CLI and MCP coverage

| Step           | CLI                                              | MCP                              | cURL                                    |
| -------------- | ------------------------------------------------ | -------------------------------- | --------------------------------------- |
| List templates | `notifications list`                             | `list_notifications`             | `GET /notifications`                    |
| Create         | `notifications create`                           | `create_notification`            | `POST /notifications`                   |
| Read draft     | `notifications retrieve-content --version draft` | `get_notification_draft_content` | `GET /notifications/{id}/draft/content` |
| Update content | `notifications put-content`                      | `put_notification_content`       | `PUT /notifications/{id}/draft/content` |
| Publish        | `notifications publish`                          | `publish_notification`           | `POST /notifications/{id}/publish`      |
| Read published | `notifications retrieve-content`                 | `get_notification_content`       | `GET /notifications/{id}/content`       |
| Send           | `send message`                                   | `send_message_template`          | `POST /send`                            |
| Versions       | `notifications list-versions`                    | `list_notification_versions`     | `GET /notifications/{id}/versions`      |
| Archive        | `notifications archive`                          | `archive_notification`           | `DELETE /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](/platform/workspaces/environments-api-keys) 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

<CardGroup cols={2}>
  <Card title="CLI reference" icon="terminal" href="/tools/cli">
    Full command list, flags, and recipes
  </Card>

  <Card title="MCP server" icon="microchip-ai" href="/tools/mcp">
    All MCP tools and IDE setup
  </Card>

  <Card title="Templates API reference" icon="book" href="/platform/content/templates-api">
    Endpoint details and content schema
  </Card>

  <Card title="Templates API tutorial" icon="code" href="/tutorials/content/how-to-use-templates-api">
    Same workflow with curl, Node.js, and Python SDK examples
  </Card>
</CardGroup>
