Skip to main content
By the end of this walkthrough, you will know how to create a workspace template from code, publish it so recipients can see it, confirm the published body, and send a real message that uses your template and variable data. You will also see how routing ties a template to your delivery setup, which is required when creating templates through the API. The example is a small shipping update email. For endpoint lists and API Reference links, check out the Templates API docs; for Elemental block patterns, see our Elemental tutorial.
Authenticate with your workspace API key. GET /notifications can return both Classic and Elemental rows; inspect each item if you need a single editor type.

Prerequisites

  • Courier API key
  • curl for the examples (the bash flow uses jq to read ids from JSON responses)
  • A routing strategy id (strategy_id inside routing on a template). Copy it from any template that already has routing configured: open the template in Studio, or call GET /notifications/{id} and read routing.strategy_id.
Export:
export COURIER_API_KEY="your_api_key"
export ROUTING_STRATEGY_ID="rs_..."   # from GET /notifications/{id} or Studio
export RECIPIENT_EMAIL="you@example.com"   # or use user_id in Step 5
Creating a template returns a Courier template id (for example nt_...). The steps below store that in TEMPLATE_ID after the create call.

Step 1: List templates

See what is already on the workspace. The response is paginated; use cursor from paging for the next page if you need it.
cURL
curl -s "https://api.courier.com/notifications" \
  -H "Authorization: Bearer $COURIER_API_KEY" \
  -H "Accept: application/json" | jq .

Step 2: Create a draft with Elemental content

Create a new notification template with POST /notifications. The body is published, plus a notification object: metadata (name, tags, brand, subscription), routing with a strategy_id from your workspace, and content in the Elemental shape (version and elements). Courier returns a template id (commonly nt_...); use that value as TEMPLATE_ID in the following steps.
To replace an existing template in full, use PUT /notifications/{id} with the same notification object shape. See Replace Notification Template. To create without overwriting, keep using POST /notifications as below. If validation fails, compare your payload to Create Notification Template.
RESP=$(curl -sS -X POST "https://api.courier.com/notifications" \
  -H "Authorization: Bearer $COURIER_API_KEY" \
  -H "Content-Type: application/json" \
  -d "$(jq -n \
    --arg sid "$ROUTING_STRATEGY_ID" \
    '{
      "published": false,
      "notification": {
        "name": "Shipping Update API Tutorial",
        "tags": [],
        "brand": null,
        "subscription": null,
        "routing": { "strategy_id": $sid },
        "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: {{tracking_url}}."
            },
            {
              "type": "action",
              "content": "Track shipment",
              "href": "{{tracking_url}}"
            }
          ]
        }
      }
    }')")

echo "$RESP" | jq .
export TEMPLATE_ID=$(echo "$RESP" | jq -r '.notification.id')
echo "TEMPLATE_ID=$TEMPLATE_ID"

Step 3: Publish

Publish the current draft (or a specific version) with POST /notifications/{id}/publish.
cURL
curl -X POST "https://api.courier.com/notifications/$TEMPLATE_ID/publish" \
  -H "Authorization: Bearer $COURIER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Step 4: Read published content

Confirm what is live:
cURL
curl -s "https://api.courier.com/notifications/$TEMPLATE_ID/content" \
  -H "Authorization: Bearer $COURIER_API_KEY" \
  -H "Accept: application/json" | jq .

Step 5: Send a message with your template

Call POST /send with your template id and values for the variables used in the draft (order_id, name, tracking_url). Put the recipient in message.to; the example below uses email. You can send to a Courier profile with to: { "user_id": "..." } instead. See Send a message for all to shapes.
The template must have a delivery channel and provider configured in Studio (for example email) or the send can fail routing. Use a Test API key while iterating.
curl -X POST "https://api.courier.com/send" \
  -H "Authorization: Bearer $COURIER_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<EOF
{
  "message": {
    "template": "${TEMPLATE_ID}",
    "to": { "email": "${RECIPIENT_EMAIL}" },
    "data": {
      "order_id": "ORD-1001",
      "name": "Alex",
      "tracking_url": "https://example.com/track/ORD-1001"
    }
  }
}
EOF
Check message logs for delivery status.

What you built

You listed workspace templates, created a draft with Elemental content and routing, published it, read the published blocks, and sent a message that references the returned template id.

What’s Next

Templates API reference

Endpoints, scope, and links to API Reference

How to Build Notifications with Elemental

Patterns for content and channel overrides

Send API

Request body, profiles, and routing

Sending overview

Strategies, channels, and production sending