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

# Send email with Postmark through Courier

> Connect Postmark with a server token, then override MessageStream, attachments, and templates.

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

export const AppLink = ({href, children, name, bare}) => {
  const label = children || name || "Open in Courier";
  if (bare) {
    return <a href={href} target="_blank" rel="noreferrer">{label}</a>;
  }
  return <a className="cx-endpoint" data-kind="app" href={href} target="_blank" rel="noreferrer">
      <span className="cx-endpoint-label">{label}</span>
      <span className="cx-endpoint-method" aria-hidden="true">↗</span>
    </a>;
};

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>;
};

## Prerequisites

* [A Postmark account with a verified sender signature](https://postmarkapp.com/)
* Your Postmark Server API Token

## Setup

<Steps>
  <Step title="Get your Postmark server token">
    In Postmark, open the server you send from and copy its [Server API token](https://postmarkapp.com/support/article/1008-what-are-the-account-and-server-api-tokens).
  </Step>

  <Step title="Configure in Courier">
    Open the <AppLink href="https://app.courier.com/integrations/catalog/postmark">Postmark integration</AppLink> in Courier, enter your API token and From Address, then save.
  </Step>
</Steps>

Addressing a recipient and sending are the same on every email provider, so they are documented once: <Doc href="/docs/integrations/email/overview#profile-requirements">profile requirements</Doc> and <Doc href="/docs/integrations/email/overview#send-to-a-recipient">send to a recipient</Doc>.

## Subject character limit

<Info>
  The Postmark API limits subject lines to \~60 characters. Emojis and special characters lower that limit because of encoding.
</Info>

## Overrides

<Doc href="/docs/send/overrides#how-overrides-work">How overrides work</Doc> covers the two levels and which one wins. <Doc href="/docs/integrations/email/overview#channel-overrides">Email channel overrides</Doc> lists the fields every email provider takes.

A provider override changes what Courier sends to Postmark's Email API. This example adds a [MessageStream](https://postmarkapp.com/support/article/1207-how-to-create-and-send-through-message-streams) and an attachment:

<CodeGroup>
  ```javascript Node.js highlight={8-23} theme={null}
  const { requestId } = await courier.send.message({
    message: {
      template: "nt_01kx4h2jdafq8bk9aftxak4b40",
      to: {
        email: "sarah@acme-corp.com",
      },
      providers: {
        postmark: {
          override: {
            config: {
              MessageStream: "message_stream_id",
            },
            body: {
              Attachments: [
                {
                  Name: "readme.txt",
                  Content: "dGVzdCBjb250ZW50",
                  ContentType: "text/plain",
                },
              ],
            },
          },
        },
      },
    },
  });
  ```

  ```python Python highlight={8-23} theme={null}
  response = client.send.message(
      message={
          "template": "nt_01kx4h2jdafq8bk9aftxak4b40",
          "to": {
              "email": "sarah@acme-corp.com",
          },
          "providers": {
              "postmark": {
                  "override": {
                      "config": {
                          "MessageStream": "message_stream_id",
                      },
                      "body": {
                          "Attachments": [
                              {
                                  "Name": "readme.txt",
                                  "Content": "dGVzdCBjb250ZW50",
                                  "ContentType": "text/plain",
                              },
                          ],
                      },
                  },
              },
          },
      },
  )
  ```

  ```bash cURL highlight={11-26} 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": "nt_01kx4h2jdafq8bk9aftxak4b40",
        "to": {
          "email": "sarah@acme-corp.com"
        },
        "providers": {
          "postmark": {
            "override": {
              "config": {
                "MessageStream": "message_stream_id"
              },
              "body": {
                "Attachments": [
                  {
                    "Name": "readme.txt",
                    "Content": "dGVzdCBjb250ZW50",
                    "ContentType": "text/plain"
                  }
                ]
              }
            }
          }
        }
      }
    }'
  ```

  ```ruby Ruby highlight={8-23} theme={null}
  response = courier.send_.message(
    message: {
      template: "nt_01kx4h2jdafq8bk9aftxak4b40",
      to: {
        email: "sarah@acme-corp.com"
      },
      providers: {
        postmark: {
          override: {
            config: {
              MessageStream: "message_stream_id"
            },
            body: {
              Attachments: [
                {
                  Name: "readme.txt",
                  Content: "dGVzdCBjb250ZW50",
                  ContentType: "text/plain"
                }
              ]
            }
          }
        }
      }
    }
  )
  ```

  ```go Go highlight={10-25} theme={null}
  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"),
  			},
  		},
  		Template: courier.String("nt_01kx4h2jdafq8bk9aftxak4b40"),
  		Providers: shared.MessageProvidersParam{
  			"postmark": shared.MessageProvidersTypeParam{
  				Override: map[string]any{
  					"config": map[string]any{
  						"MessageStream": "message_stream_id",
  					},
  					"body": map[string]any{
  						"Attachments": []any{
  							map[string]any{
  								"Name": "readme.txt",
  								"Content": "dGVzdCBjb250ZW50",
  								"ContentType": "text/plain",
  							},
  						},
  					},
  				},
  			},
  		},
  	},
  })
  ```

  ```java Java highlight={6-19} theme={null}
  SendMessageParams params = SendMessageParams.builder()
      .message(SendMessageParams.Message.builder()
          .to(UserRecipient.builder().email("sarah@acme-corp.com").build())
          .template("nt_01kx4h2jdafq8bk9aftxak4b40")
          .providers(MessageProviders.builder()
              .putAdditionalProperty("postmark", JsonValue.from(java.util.Map.of("override", java.util.Map.of(
                      "config", java.util.Map.of(
                          "MessageStream", "message_stream_id"
                      ),
                      "body", java.util.Map.of(
                          "Attachments", java.util.List.of(
                              java.util.Map.of(
                                  "Name", "readme.txt",
                                  "Content", "dGVzdCBjb250ZW50",
                                  "ContentType", "text/plain"
                              )
                          )
                      )
                  ))))
              .build())
          .build())
      .build();
  SendMessageResponse response = client.send().message(params);
  ```

  ```php PHP highlight={8-23} theme={null}
  $response = $client->send->message(
    message: [
      'template' => 'nt_01kx4h2jdafq8bk9aftxak4b40',
      'to' => [
        'email' => 'sarah@acme-corp.com',
      ],
      'providers' => [
        'postmark' => [
          'override' => [
            'config' => [
              'MessageStream' => 'message_stream_id',
            ],
            'body' => [
              'Attachments' => [
                [
                  'Name' => 'readme.txt',
                  'Content' => 'dGVzdCBjb250ZW50',
                  'ContentType' => 'text/plain',
                ],
              ],
            ],
          ],
        ],
      ],
    ],
  );
  ```

  ```csharp C# highlight={9-32} theme={null}
  SendMessageParams parameters = new()
  {
      Message = new()
      {
          To = new UserRecipient { Email = "sarah@acme-corp.com" },
          Template = "nt_01kx4h2jdafq8bk9aftxak4b40",
          Providers = new Dictionary<string, MessageProvidersType>()
          {
              {
                  "postmark",
                  new()
                  {
                      Override = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(
                          """
                          {
                            "config": {
                              "MessageStream": "message_stream_id"
                            },
                            "body": {
                              "Attachments": [
                                {
                                  "Name": "readme.txt",
                                  "Content": "dGVzdCBjb250ZW50",
                                  "ContentType": "text/plain"
                                }
                              ]
                            }
                          }
                          """
                      ),
                  }
              },
          },
      },
  };

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

  ```bash CLI highlight={5} wrap theme={null}
  courier send message \
    --api-key "$COURIER_API_KEY" \
    --message.to '{"email": "sarah@acme-corp.com"}' \
    --message.template nt_01kx4h2jdafq8bk9aftxak4b40 \
    --message.providers '{"postmark": {"override": {"config": {"MessageStream": "message_stream_id"}, "body": {"Attachments": [{"Name": "readme.txt", "Content": "dGVzdCBjb250ZW50", "ContentType": "text/plain"}]}}}}'
  ```

  ```text MCP theme={null}
  With Courier MCP, send my template to sarah@acme-corp.com on my Postmark broadcast message stream.
  ```
</CodeGroup>

Overrides are deep-merged into the request. Fields you set replace their counterparts, and everything you leave out is still sent. For every option, see the [Postmark API docs](https://postmarkapp.com/developer/api/email-api).

`override.config.fromAddress` swaps the sender for one message, in place of the From Address saved on the integration. A template **From** value or a `channels.email.override.from` still wins over it. <Guide href="/docs/guides/send-from-your-domain">Send from your own domain</Guide> covers the order.

## Using Postmark templates

<CodeGroup>
  ```javascript Node.js highlight={9-33} theme={null}
  const { requestId } = await courier.send.message({
    message: {
      to: {
        email: "sarah@acme-corp.com",
      },
      template: "nt_01kx4h2jdafq8bk9aftxak4b40",
      providers: {
        postmark: {
          override: {
            config: {
              url: "https://api.postmarkapp.com/email/withTemplate",
            },
            body: {
              TemplateId: "123456",
              TemplateModel: {
                product_url: "product_url_Value",
                product_name: "product_name_Value",
                name: "name_Value",
                action_url: "action_url_Value",
                login_url: "login_url_Value",
                username: "username_Value",
                trial_length: "trial_length_Value",
                trial_start_date: "trial_start_date_Value",
                trial_end_date: "trial_end_date_Value",
                support_email: "support_email_Value",
                live_chat_url: "live_chat_url_Value",
                sender_name: "sender_name_Value",
                help_url: "help_url_Value",
                company_name: "company_name_Value",
                company_address: "company_address_Value",
              },
            },
          },
        },
      },
    },
  });
  ```

  ```python Python highlight={9-33} theme={null}
  response = client.send.message(
      message={
          "to": {
              "email": "sarah@acme-corp.com",
          },
          "template": "nt_01kx4h2jdafq8bk9aftxak4b40",
          "providers": {
              "postmark": {
                  "override": {
                      "config": {
                          "url": "https://api.postmarkapp.com/email/withTemplate",
                      },
                      "body": {
                          "TemplateId": "123456",
                          "TemplateModel": {
                              "product_url": "product_url_Value",
                              "product_name": "product_name_Value",
                              "name": "name_Value",
                              "action_url": "action_url_Value",
                              "login_url": "login_url_Value",
                              "username": "username_Value",
                              "trial_length": "trial_length_Value",
                              "trial_start_date": "trial_start_date_Value",
                              "trial_end_date": "trial_end_date_Value",
                              "support_email": "support_email_Value",
                              "live_chat_url": "live_chat_url_Value",
                              "sender_name": "sender_name_Value",
                              "help_url": "help_url_Value",
                              "company_name": "company_name_Value",
                              "company_address": "company_address_Value",
                          },
                      },
                  },
              },
          },
      },
  )
  ```

  ```bash cURL highlight={12-36} wrap 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"
        },
        "template": "nt_01kx4h2jdafq8bk9aftxak4b40",
        "providers": {
          "postmark": {
            "override": {
              "config": {
                "url": "https://api.postmarkapp.com/email/withTemplate"
              },
              "body": {
                "TemplateId": "123456",
                "TemplateModel": {
                  "product_url": "product_url_Value",
                  "product_name": "product_name_Value",
                  "name": "name_Value",
                  "action_url": "action_url_Value",
                  "login_url": "login_url_Value",
                  "username": "username_Value",
                  "trial_length": "trial_length_Value",
                  "trial_start_date": "trial_start_date_Value",
                  "trial_end_date": "trial_end_date_Value",
                  "support_email": "support_email_Value",
                  "live_chat_url": "live_chat_url_Value",
                  "sender_name": "sender_name_Value",
                  "help_url": "help_url_Value",
                  "company_name": "company_name_Value",
                  "company_address": "company_address_Value"
                }
              }
            }
          }
        }
      }
    }'
  ```

  ```ruby Ruby highlight={9-33} theme={null}
  response = courier.send_.message(
    message: {
      to: {
        email: "sarah@acme-corp.com"
      },
      template: "nt_01kx4h2jdafq8bk9aftxak4b40",
      providers: {
        postmark: {
          override: {
            config: {
              url: "https://api.postmarkapp.com/email/withTemplate"
            },
            body: {
              TemplateId: "123456",
              TemplateModel: {
                product_url: "product_url_Value",
                product_name: "product_name_Value",
                name: "name_Value",
                action_url: "action_url_Value",
                login_url: "login_url_Value",
                username: "username_Value",
                trial_length: "trial_length_Value",
                trial_start_date: "trial_start_date_Value",
                trial_end_date: "trial_end_date_Value",
                support_email: "support_email_Value",
                live_chat_url: "live_chat_url_Value",
                sender_name: "sender_name_Value",
                help_url: "help_url_Value",
                company_name: "company_name_Value",
                company_address: "company_address_Value"
              }
            }
          }
        }
      }
    }
  )
  ```

  ```go Go highlight={11-35} theme={null}
  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"),
  			},
  		},
  		Template: courier.String("nt_01kx4h2jdafq8bk9aftxak4b40"),
  		Providers: shared.MessageProvidersParam{
  			"postmark": shared.MessageProvidersTypeParam{
  				Override: map[string]any{
  					"config": map[string]any{
  						"url": "https://api.postmarkapp.com/email/withTemplate",
  					},
  					"body": map[string]any{
  						"TemplateId": "123456",
  						"TemplateModel": map[string]any{
  							"product_url": "product_url_Value",
  							"product_name": "product_name_Value",
  							"name": "name_Value",
  							"action_url": "action_url_Value",
  							"login_url": "login_url_Value",
  							"username": "username_Value",
  							"trial_length": "trial_length_Value",
  							"trial_start_date": "trial_start_date_Value",
  							"trial_end_date": "trial_end_date_Value",
  							"support_email": "support_email_Value",
  							"live_chat_url": "live_chat_url_Value",
  							"sender_name": "sender_name_Value",
  							"help_url": "help_url_Value",
  							"company_name": "company_name_Value",
  							"company_address": "company_address_Value",
  						},
  					},
  				},
  			},
  		},
  	},
  })
  ```

  ```java Java highlight={6-30} theme={null}
  SendMessageParams params = SendMessageParams.builder()
      .message(SendMessageParams.Message.builder()
          .to(UserRecipient.builder().email("sarah@acme-corp.com").build())
          .template("nt_01kx4h2jdafq8bk9aftxak4b40")
          .providers(MessageProviders.builder()
              .putAdditionalProperty("postmark", JsonValue.from(java.util.Map.of("override", java.util.Map.of(
                      "config", java.util.Map.of(
                          "url", "https://api.postmarkapp.com/email/withTemplate"
                      ),
                      "body", java.util.Map.of(
                          "TemplateId", "123456",
                          "TemplateModel", java.util.Map.of(
                              "product_url", "product_url_Value",
                              "product_name", "product_name_Value",
                              "name", "name_Value",
                              "action_url", "action_url_Value",
                              "login_url", "login_url_Value",
                              "username", "username_Value",
                              "trial_length", "trial_length_Value",
                              "trial_start_date", "trial_start_date_Value",
                              "trial_end_date", "trial_end_date_Value",
                              "support_email", "support_email_Value",
                              "live_chat_url", "live_chat_url_Value",
                              "sender_name", "sender_name_Value",
                              "help_url", "help_url_Value",
                              "company_name", "company_name_Value",
                              "company_address", "company_address_Value"
                          )
                      )
                  ))))
              .build())
          .build())
      .build();
  SendMessageResponse response = client.send().message(params);
  ```

  ```php PHP highlight={9-33} theme={null}
  $response = $client->send->message(
    message: [
      'to' => [
        'email' => 'sarah@acme-corp.com',
      ],
      'template' => 'nt_01kx4h2jdafq8bk9aftxak4b40',
      'providers' => [
        'postmark' => [
          'override' => [
            'config' => [
              'url' => 'https://api.postmarkapp.com/email/withTemplate',
            ],
            'body' => [
              'TemplateId' => '123456',
              'TemplateModel' => [
                'product_url' => 'product_url_Value',
                'product_name' => 'product_name_Value',
                'name' => 'name_Value',
                'action_url' => 'action_url_Value',
                'login_url' => 'login_url_Value',
                'username' => 'username_Value',
                'trial_length' => 'trial_length_Value',
                'trial_start_date' => 'trial_start_date_Value',
                'trial_end_date' => 'trial_end_date_Value',
                'support_email' => 'support_email_Value',
                'live_chat_url' => 'live_chat_url_Value',
                'sender_name' => 'sender_name_Value',
                'help_url' => 'help_url_Value',
                'company_name' => 'company_name_Value',
                'company_address' => 'company_address_Value',
              ],
            ],
          ],
        ],
      ],
    ],
  );
  ```

  ```csharp C# highlight={13-41} theme={null}
  SendMessageParams parameters = new()
  {
      Message = new()
      {
          To = new UserRecipient { Email = "sarah@acme-corp.com" },
          Template = "nt_01kx4h2jdafq8bk9aftxak4b40",
          Providers = new Dictionary<string, MessageProvidersType>()
          {
              {
                  "postmark",
                  new()
                  {
                      Override = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(
                          """
                          {
                            "config": {
                              "url": "https://api.postmarkapp.com/email/withTemplate"
                            },
                            "body": {
                              "TemplateId": "123456",
                              "TemplateModel": {
                                "product_url": "product_url_Value",
                                "product_name": "product_name_Value",
                                "name": "name_Value",
                                "action_url": "action_url_Value",
                                "login_url": "login_url_Value",
                                "username": "username_Value",
                                "trial_length": "trial_length_Value",
                                "trial_start_date": "trial_start_date_Value",
                                "trial_end_date": "trial_end_date_Value",
                                "support_email": "support_email_Value",
                                "live_chat_url": "live_chat_url_Value",
                                "sender_name": "sender_name_Value",
                                "help_url": "help_url_Value",
                                "company_name": "company_name_Value",
                                "company_address": "company_address_Value"
                              }
                            }
                          }
                          """
                      ),
                  }
              },
          },
      },
  };

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

  ```bash CLI highlight={5} wrap theme={null}
  courier send message \
    --api-key "$COURIER_API_KEY" \
    --message.to '{"email": "sarah@acme-corp.com"}' \
    --message.template nt_01kx4h2jdafq8bk9aftxak4b40 \
    --message.providers '{"postmark": {"override": {"config": {"url": "https://api.postmarkapp.com/email/withTemplate"}, "body": {"TemplateId": "123456", "TemplateModel": {"product_url": "product_url_Value", "product_name": "product_name_Value", "name": "name_Value", "action_url": "action_url_Value", "login_url": "login_url_Value", "username": "username_Value", "trial_length": "trial_length_Value", "trial_start_date": "trial_start_date_Value", "trial_end_date": "trial_end_date_Value", "support_email": "support_email_Value", "live_chat_url": "live_chat_url_Value", "sender_name": "sender_name_Value", "help_url": "help_url_Value", "company_name": "company_name_Value", "company_address": "company_address_Value"}}}}}'
  ```

  ```text MCP theme={null}
  With Courier MCP, send my template to sarah@acme-corp.com and render it with a Postmark template.
  ```
</CodeGroup>

The `message.providers.postmark.override.config` property replaces Courier templates with Postmark's [Templates API](https://postmarkapp.com/developer/api/templates-api).

Include the `https://api.postmarkapp.com/email/withTemplate` URL in the config object, and `TemplateId` and `TemplateModel` in the body.

<Warning>
  With Postmark templates, your request must use a `template` parameter, not `content`. Otherwise `content` takes precedence over the Postmark override. An invalid `template_id` causes an error.
</Warning>

## Provider details

```text theme={null}
postmark
```

Courier recommends routing to the channel. Naming this key in `routing.channels` instead is supported, and sends through just this provider.

<Card title="Send to a specific provider" icon="bullseye-arrow" href="/docs/send/send-to-a-provider" horizontal arrow="true">
  When that is worth doing, and what you give up: failover, channel priority, and providers you add later.
</Card>
