Prerequisites
Setup
1
Create a Resend API Key
In Resend, open API Keys. Create an API key and copy it.
2
Configure in Courier
In Courier, open the page. Paste your API key into the “API Key” field.
3
Set From Address
Add a verified email address to the “From Address” field (e.g.,
noreply@yourdomain.com). Click “Add Integration” then “Save.”Overrides
covers the two levels and which one wins. lists the fields every email provider takes. A provider override changes what Courier sends to Resend’s /emails endpoint. Use one to set a field Courier does not support yet, or to replace a value Courier generates. For example, add Resend tags:const { requestId } = await courier.send.message({
message: {
template: "nt_01kx4h2jdafq8bk9aftxak4b40",
to: {
email: "sarah@acme-corp.com",
},
providers: {
resend: {
override: {
body: {
tags: [
{
name: "environment",
value: "development",
},
],
},
},
},
},
},
});
response = client.send.message(
message={
"template": "nt_01kx4h2jdafq8bk9aftxak4b40",
"to": {
"email": "sarah@acme-corp.com",
},
"providers": {
"resend": {
"override": {
"body": {
"tags": [
{
"name": "environment",
"value": "development",
},
],
},
},
},
},
},
)
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": {
"resend": {
"override": {
"body": {
"tags": [
{
"name": "environment",
"value": "development"
}
]
}
}
}
}
}
}'
response = courier.send_.message(
message: {
template: "nt_01kx4h2jdafq8bk9aftxak4b40",
to: {
email: "sarah@acme-corp.com"
},
providers: {
resend: {
override: {
body: {
tags: [
{
name: "environment",
value: "development"
}
]
}
}
}
}
}
)
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{
"resend": shared.MessageProvidersTypeParam{
Override: map[string]any{
"body": map[string]any{
"tags": []any{
map[string]any{
"name": "environment",
"value": "development",
},
},
},
},
},
},
},
})
SendMessageParams params = SendMessageParams.builder()
.message(SendMessageParams.Message.builder()
.to(UserRecipient.builder().email("sarah@acme-corp.com").build())
.template("nt_01kx4h2jdafq8bk9aftxak4b40")
.providers(MessageProviders.builder()
.putAdditionalProperty("resend", JsonValue.from(java.util.Map.of("override", java.util.Map.of(
"body", java.util.Map.of(
"tags", java.util.List.of(
java.util.Map.of(
"name", "environment",
"value", "development"
)
)
)
))))
.build())
.build())
.build();
SendMessageResponse response = client.send().message(params);
$response = $client->send->message(
message: [
'template' => 'nt_01kx4h2jdafq8bk9aftxak4b40',
'to' => [
'email' => 'sarah@acme-corp.com',
],
'providers' => [
'resend' => [
'override' => [
'body' => [
'tags' => [
[
'name' => 'environment',
'value' => 'development',
],
],
],
],
],
],
],
);
SendMessageParams parameters = new()
{
Message = new()
{
To = new UserRecipient { Email = "sarah@acme-corp.com" },
Template = "nt_01kx4h2jdafq8bk9aftxak4b40",
Providers = new Dictionary<string, MessageProvidersType>()
{
{
"resend",
new()
{
Override = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(
"""
{
"body": {
"tags": [
{
"name": "environment",
"value": "development"
}
]
}
}
"""
),
}
},
},
},
};
var response = await client.Send.Message(parameters);
courier send message \
--api-key "$COURIER_API_KEY" \
--message.to '{"email": "sarah@acme-corp.com"}' \
--message.template nt_01kx4h2jdafq8bk9aftxak4b40 \
--message.providers '{"resend": {"override": {"body": {"tags": [{"name": "environment", "value": "development"}]}}}}'
With Courier MCP, send my template to sarah@acme-corp.com and set a Resend field Courier does not expose.
message.providers.resend.override.body into its generated request body. You can also override config values:
{
"message": {
"providers": {
"resend": {
"override": {
"config": {
"apiKey": "<your override API key>",
"fromAddress": "alternate-sender@yourdomain.com"
}
}
}
}
}
}
Attachments
To include an attachment, add anattachments array in the override. File content must be base64-encoded.
const { requestId } = await courier.send.message({
message: {
template: "nt_01kx4h2jdafq8bk9aftxak4b40",
to: {
email: "sarah@acme-corp.com",
},
providers: {
resend: {
override: {
attachments: [
{
filename: "billing.pdf",
contentType: "application/pdf",
data: "Q29uZ3JhdHVsYXRpb25zLCB5b3UgY2FuIGJhc2U2NCBkZWNvZGUh",
},
],
},
},
},
},
});
response = client.send.message(
message={
"template": "nt_01kx4h2jdafq8bk9aftxak4b40",
"to": {
"email": "sarah@acme-corp.com",
},
"providers": {
"resend": {
"override": {
"attachments": [
{
"filename": "billing.pdf",
"contentType": "application/pdf",
"data": "Q29uZ3JhdHVsYXRpb25zLCB5b3UgY2FuIGJhc2U2NCBkZWNvZGUh",
},
],
},
},
},
},
)
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": {
"resend": {
"override": {
"attachments": [
{
"filename": "billing.pdf",
"contentType": "application/pdf",
"data": "Q29uZ3JhdHVsYXRpb25zLCB5b3UgY2FuIGJhc2U2NCBkZWNvZGUh"
}
]
}
}
}
}
}'
response = courier.send_.message(
message: {
template: "nt_01kx4h2jdafq8bk9aftxak4b40",
to: {
email: "sarah@acme-corp.com"
},
providers: {
resend: {
override: {
attachments: [
{
filename: "billing.pdf",
contentType: "application/pdf",
data: "Q29uZ3JhdHVsYXRpb25zLCB5b3UgY2FuIGJhc2U2NCBkZWNvZGUh"
}
]
}
}
}
}
)
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{
"resend": shared.MessageProvidersTypeParam{
Override: map[string]any{
"attachments": []any{
map[string]any{
"filename": "billing.pdf",
"contentType": "application/pdf",
"data": "Q29uZ3JhdHVsYXRpb25zLCB5b3UgY2FuIGJhc2U2NCBkZWNvZGUh",
},
},
},
},
},
},
})
SendMessageParams params = SendMessageParams.builder()
.message(SendMessageParams.Message.builder()
.to(UserRecipient.builder().email("sarah@acme-corp.com").build())
.template("nt_01kx4h2jdafq8bk9aftxak4b40")
.providers(MessageProviders.builder()
.putAdditionalProperty("resend", JsonValue.from(java.util.Map.of("override", java.util.Map.of(
"attachments", java.util.List.of(
java.util.Map.of(
"filename", "billing.pdf",
"contentType", "application/pdf",
"data", "Q29uZ3JhdHVsYXRpb25zLCB5b3UgY2FuIGJhc2U2NCBkZWNvZGUh"
)
)
))))
.build())
.build())
.build();
SendMessageResponse response = client.send().message(params);
$response = $client->send->message(
message: [
'template' => 'nt_01kx4h2jdafq8bk9aftxak4b40',
'to' => [
'email' => 'sarah@acme-corp.com',
],
'providers' => [
'resend' => [
'override' => [
'attachments' => [
[
'filename' => 'billing.pdf',
'contentType' => 'application/pdf',
'data' => 'Q29uZ3JhdHVsYXRpb25zLCB5b3UgY2FuIGJhc2U2NCBkZWNvZGUh',
],
],
],
],
],
],
);
SendMessageParams parameters = new()
{
Message = new()
{
To = new UserRecipient { Email = "sarah@acme-corp.com" },
Template = "nt_01kx4h2jdafq8bk9aftxak4b40",
Providers = new Dictionary<string, MessageProvidersType>()
{
{
"resend",
new()
{
Override = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(
"""
{
"attachments": [
{
"filename": "billing.pdf",
"contentType": "application/pdf",
"data": "Q29uZ3JhdHVsYXRpb25zLCB5b3UgY2FuIGJhc2U2NCBkZWNvZGUh"
}
]
}
"""
),
}
},
},
},
};
var response = await client.Send.Message(parameters);
courier send message \
--api-key "$COURIER_API_KEY" \
--message.to '{"email": "sarah@acme-corp.com"}' \
--message.template nt_01kx4h2jdafq8bk9aftxak4b40 \
--message.providers '{"resend": {"override": {"attachments": [{"filename": "billing.pdf", "contentType": "application/pdf", "data": "Q29uZ3JhdHVsYXRpb25zLCB5b3UgY2FuIGJhc2U2NCBkZWNvZGUh"}]}}}'
With Courier MCP, send my template to sarah@acme-corp.com with an attachment through Resend.
Provider details
resend
routing.channels instead is supported, and sends through just this provider.
Send to a specific provider
When that is worth doing, and what you give up: failover, channel priority, and providers you add later.