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

> ## Agent Instructions
> Install the Courier skill before writing code: `npx skills add trycourier/courier-skills`. It carries the verified SDK shapes and the rules you cannot get wrong.
> Authenticate every request with `Authorization: Bearer <API_KEY>`. A workspace has several environments and each has its own keys, which are plain `pk_` strings with no environment prefix. Start with Test.
> Send with `client.send.message`, the default import of the v7 Node SDK. Reference a template by its `nt_` id or its alias.
> A send accepts a bare Elemental element list, but storing content on a template requires the top-level elements wrapped in a channel element.
> Templates and journeys can be built in the Courier app or created through the API. Either way they live in the workspace and are referenced by ID when you send.
> The hosted MCP server is https://mcp.courier.com. For a briefing on what Courier is and when to use it, read https://www.courier.com/llms.txt.
> Prefer the Guides tab for how-do-I questions and the Docs tab for how-does-it-behave questions. The API reference lives under /api-reference.

# Elemental action element

> Add a button or link with a label, href, and style, rendered per channel.

export const Doc = ({href, children, name, bare}) => {
  const label = children || name || href;
  if (bare) {
    return <a href={href}>{label}</a>;
  }
  return <a className="cx-endpoint" data-kind="doc" href={href}>
      <span className="cx-endpoint-label">{label}</span>
      <span className="cx-endpoint-method">DOC</span>
    </a>;
};

The action element adds a clickable action to your notification. It renders as a button or a link, depending on the channel and styling options you choose. The type value is `"action"`.

**When to use:**

* Add call-to-action buttons (e.g., "Sign Up", "View Order", "Confirm Email")
* Create clickable links within notifications
* Provide interactive elements that direct users to specific URLs

**Basic example**

<CodeGroup>
  ```json Elemental theme={null}
  {
    "type": "action",
    "content": "Click me",
    "href": "https://example.com"
  }
  ```

  ```javascript Node.js highlight={9-13} theme={null}
  const { requestId } = await client.send.message({
    message: {
      to: {
        email: "sarah@acme-corp.com",
      },
      content: {
        version: "2022-01-01",
        elements: [
          {
            type: "action",
            content: "Click me",
            href: "https://example.com",
          },
        ],
      },
    },
  });
  ```

  ```python Python highlight={9-13} theme={null}
  response = client.send.message(
      message={
        "to": {
          "email": "sarah@acme-corp.com",
        },
        "content": {
          "version": "2022-01-01",
          "elements": [
            {
              "type": "action",
              "content": "Click me",
              "href": "https://example.com",
            },
          ],
        },
      },
  )
  ```

  ```bash cURL highlight={12-16} theme={null}
  curl -X POST https://api.courier.com/send \
    -H "Authorization: Bearer $COURIER_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
        "message": {
          "to": {
            "email": "sarah@acme-corp.com"
          },
          "content": {
            "version": "2022-01-01",
            "elements": [
              {
                "type": "action",
                "content": "Click me",
                "href": "https://example.com"
              }
            ]
          }
        }
      }'
  ```

  ```ruby Ruby highlight={9-13} theme={null}
  response = courier.send_.message(
    message: {
      to: {
        email: "sarah@acme-corp.com"
      },
      content: {
        version: "2022-01-01",
        elements: [
          {
            type: "action",
            content: "Click me",
            href: "https://example.com"
          }
        ]
      }
    }
  )
  ```

  ```go Go highlight={5-9} theme={null}
  // Elemental nodes carry no typed content fields, so pass the document as raw JSON.
  content := param.Override[shared.ElementalContentParam](json.RawMessage(`{
    "version": "2022-01-01",
    "elements": [
      {
        "type": "action",
        "content": "Click me",
        "href": "https://example.com"
      }
    ]
  }`))

  response, err := client.Send.Message(context.TODO(), courier.SendMessageParams{
  	Message: courier.SendMessageParamsMessage{
  		To: courier.SendMessageParamsMessageToUnion{
  			OfUserRecipient: &shared.UserRecipientParam{
  				Email: courier.String("sarah@acme-corp.com"),
  			},
  		},
  		Content: courier.SendMessageParamsMessageContentUnion{OfElementalContent: &content},
  	},
  })
  ```

  ```java Java highlight={7-10} theme={null}
  SendMessageParams params = SendMessageParams.builder()
      .message(SendMessageParams.Message.builder()
          .to(JsonValue.from(java.util.Map.of("email", "sarah@acme-corp.com")))
          .content(JsonValue.from(java.util.Map.of(
                  "version", "2022-01-01",
                  "elements", java.util.List.of(
                    java.util.Map.of(
                      "type", "action",
                      "content", "Click me",
                      "href", "https://example.com")))))
          .build())
      .build();
  SendMessageResponse response = client.send().message(params);
  ```

  ```php PHP highlight={9-13} theme={null}
  $response = $client->send->message(
    message: [
      'to' => [
        'email' => 'sarah@acme-corp.com',
      ],
      'content' => [
        'version' => '2022-01-01',
        'elements' => [
          [
            'type' => 'action',
            'content' => 'Click me',
            'href' => 'https://example.com',
          ],
        ],
      ],
    ],
  );
  ```

  ```csharp C# highlight={12-16} theme={null}
  // Elemental nodes expose no typed content fields, so build the document from raw JSON.
  SendMessageParams parameters = new()
  {
      Message = new()
      {
          To = new UserRecipient { Email = "sarah@acme-corp.com" },
          Content = ElementalContent.FromRawUnchecked(
              JsonSerializer.Deserialize<Dictionary<string, JsonElement>>("""
              {
                "version": "2022-01-01",
                "elements": [
                  {
                    "type": "action",
                    "content": "Click me",
                    "href": "https://example.com"
                  }
                ]
              }
              """)),
      },
  };

  var response = await client.Send.Message(parameters);
  ```

  ```bash CLI highlight={4} theme={null}
  courier send message \
    --api-key "$COURIER_API_KEY" \
    --message.to '{"email": "sarah@acme-corp.com"}' \
    --message.content '{"version": "2022-01-01", "elements": [{"type": "action", "content": "Click me", "href": "https://example.com"}]}'
  ```

  ```text MCP theme={null}
  With Courier MCP, send an email to sarah@acme-corp.com with a button linking to our dashboard.
  ```
</CodeGroup>

**Fields**

<ParamField path="content" type="string" required>
  The label displayed on the button or link.
</ParamField>

<ParamField path="href" type="string" required>
  The target URL of the action. Clicking it sends the user to this URL.
</ParamField>

<ParamField path="action_id" type="string">
  A unique identifier for the action when it is executed. Useful for tracking and analytics.
</ParamField>

<ParamField path="align" type="string">
  The alignment of the action button. One of `"center"`, `"left"`, `"right"`, or `"full"`. Defaults to `"center"`.
</ParamField>

<ParamField path="background_color" type="string">
  The background color of the action button. Any valid CSS color value (e.g., `"#007bff"`, `"rgb(0, 123, 255)"`).
</ParamField>

<ParamField path="style" type="string">
  The visual style of the action. Defaults to `"button"`.

  * `"button"`: a filled button. `background_color` is the fill.
  * `"secondary"`: an outlined button. `background_color` is the border and the label.
  * `"tertiary"`: the quietest button. `background_color` is the label.
  * `"link"`: inline text rather than a button, and the only style that draws no button chrome.

  `background_color` is a fill only for `"button"`. Sending white with `"secondary"` asks for a white border and a white label, not a white button.
</ParamField>

<ParamField path="disable_tracking" type="boolean">
  When true, the action's `href` is not rewritten for click-through tracking, even when click-through tracking is enabled for the workspace.
</ParamField>

<ParamField path="locales" type="object">
  Region-specific content for localization. See the <Doc href="/docs/design/elemental/locales">Locales documentation</Doc>.
</ParamField>

**Examples and variants**

**Styles**

The default style renders a filled button:

```json theme={null}
{
  "type": "action",
  "content": "Get Started",
  "href": "https://example.com/start",
  "style": "button"
}
```

`"link"` renders inline text instead:

```json theme={null}
{
  "type": "action",
  "content": "Learn more",
  "href": "https://example.com/docs",
  "style": "link"
}
```

Each channel draws these as closely as its medium allows, so the three button styles are a hierarchy rather than a fixed set of pixels:

|               | Email       | Inbox                | Slack                           |
| ------------- | ----------- | -------------------- | ------------------------------- |
| `"button"`    | filled      | plain, hairline edge | button                          |
| `"secondary"` | outlined    | outlined             | button, Slack's `primary` style |
| `"tertiary"`  | underlined  | solid fill           | button, Slack's `danger` style  |
| `"link"`      | inline link | inline link          | `mrkdwn` link                   |

The Inbox reads the three buttons as a volume control rather than as email's fill, outline, and rule. `"button"` is the quiet default it has always drawn, and `"tertiary"` is the solid one.

**Styled button**

Customize the button appearance with colors and alignment:

```json theme={null}
{
  "type": "action",
  "content": "Sign Up Now",
  "href": "https://example.com/signup",
  "style": "button",
  "background_color": "#007bff",
  "align": "center"
}
```

**With localization**

Localize action content and URLs:

```json theme={null}
{
  "type": "action",
  "content": "View Dashboard",
  "href": "https://app.example.com/dashboard",
  "locales": {
    "es": {
      "content": "Ver Panel",
      "href": "https://app.example.com/es/dashboard"
    },
    "fr": {
      "content": "Voir le Tableau de Bord",
      "href": "https://app.example.com/fr/dashboard"
    }
  }
}
```

**With conditional logic**

Show different actions based on conditions:

```json theme={null}
{
  "type": "action",
  "content": "Upgrade Account",
  "href": "https://example.com/upgrade",
  "if": "{{user.plan}} === 'free'"
}
```

**Channel support**

Action elements are supported across all channels:

* **Email**: filled, outlined, or underlined, following `style`
* **Push**: a clickable action button
* **SMS**: a clickable link
* **Inbox**: an interactive button whose weight follows `style`
