aws-sns.
Amazon SNS also works as a push provider. See .
Prerequisites
- An AWS IAM user that can publish to SNS
- That user’s Access Key ID and Secret Access Key
- The AWS region you send SMS from
Setup
1
Create an AWS access key
In AWS, create an IAM user with SNS publish permission and copy its access key ID and secret access key.
2
Configure in Courier
Open the in Courier, enter your Access Key ID and Secret Access Key, choose your region, then click “Complete.”
phone_number on the profile outranks it, so a saved Topic ARN never diverts an SMS.
You add the integration once. It then appears as a provider on both the SMS and push channels.
Addressing a recipient and sending are the same on every SMS provider, so they are documented once: and .
Overrides
covers the two levels and which one wins. Theconfig override swaps the Access Key ID, Secret Access Key, or region at send time. Region defaults to us-east-1 when neither the override nor the integration sets one.
const { requestId } = await courier.send.message({
message: {
template: "nt_01kx4h2jdafq8bk9aftxak4b40",
to: {
phone_number: "+12345678901",
},
providers: {
"aws-sns": {
override: {
config: {
accessKeyId: "RUNTIME_ACCESS_KEY_ID",
secretAccessKey: "RUNTIME_SECRET_ACCESS_KEY",
region: "eu-west-1",
},
},
},
},
},
});
response = client.send.message(
message={
"template": "nt_01kx4h2jdafq8bk9aftxak4b40",
"to": {
"phone_number": "+12345678901",
},
"providers": {
"aws-sns": {
"override": {
"config": {
"accessKeyId": "RUNTIME_ACCESS_KEY_ID",
"secretAccessKey": "RUNTIME_SECRET_ACCESS_KEY",
"region": "eu-west-1",
},
},
},
},
},
)
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": {
"phone_number": "+12345678901"
},
"providers": {
"aws-sns": {
"override": {
"config": {
"accessKeyId": "RUNTIME_ACCESS_KEY_ID",
"secretAccessKey": "RUNTIME_SECRET_ACCESS_KEY",
"region": "eu-west-1"
}
}
}
}
}
}'
response = courier.send_.message(
message: {
template: "nt_01kx4h2jdafq8bk9aftxak4b40",
to: {
phone_number: "+12345678901"
},
providers: {
"aws-sns": {
override: {
config: {
accessKeyId: "RUNTIME_ACCESS_KEY_ID",
secretAccessKey: "RUNTIME_SECRET_ACCESS_KEY",
region: "eu-west-1"
}
}
}
}
}
)
response, err := client.Send.Message(context.TODO(), courier.SendMessageParams{
Message: courier.SendMessageParamsMessage{
To: courier.SendMessageParamsMessageToUnion{
OfUserRecipient: &shared.UserRecipientParam{
PhoneNumber: courier.String("+12345678901"),
},
},
Template: courier.String("nt_01kx4h2jdafq8bk9aftxak4b40"),
Providers: shared.MessageProvidersParam{
"aws-sns": shared.MessageProvidersTypeParam{
Override: map[string]any{
"config": map[string]any{
"accessKeyId": "RUNTIME_ACCESS_KEY_ID",
"secretAccessKey": "RUNTIME_SECRET_ACCESS_KEY",
"region": "eu-west-1",
},
},
},
},
},
})
SendMessageParams params = SendMessageParams.builder()
.message(SendMessageParams.Message.builder()
.to(UserRecipient.builder().phoneNumber("+12345678901").build())
.template("nt_01kx4h2jdafq8bk9aftxak4b40")
.providers(MessageProviders.builder()
.putAdditionalProperty("aws-sns", JsonValue.from(java.util.Map.of("override", java.util.Map.of(
"config", java.util.Map.of(
"accessKeyId", "RUNTIME_ACCESS_KEY_ID",
"secretAccessKey", "RUNTIME_SECRET_ACCESS_KEY",
"region", "eu-west-1"
)
))))
.build())
.build())
.build();
SendMessageResponse response = client.send().message(params);
$response = $client->send->message(
message: [
'template' => 'nt_01kx4h2jdafq8bk9aftxak4b40',
'to' => [
'phone_number' => '+12345678901',
],
'providers' => [
'aws-sns' => [
'override' => [
'config' => [
'accessKeyId' => 'RUNTIME_ACCESS_KEY_ID',
'secretAccessKey' => 'RUNTIME_SECRET_ACCESS_KEY',
'region' => 'eu-west-1',
],
],
],
],
],
);
SendMessageParams parameters = new()
{
Message = new()
{
To = new UserRecipient { PhoneNumber = "+12345678901" },
Template = "nt_01kx4h2jdafq8bk9aftxak4b40",
Providers = new Dictionary<string, MessageProvidersType>()
{
{
"aws-sns",
new()
{
Override = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(
"""
{
"config": {
"accessKeyId": "RUNTIME_ACCESS_KEY_ID",
"secretAccessKey": "RUNTIME_SECRET_ACCESS_KEY",
"region": "eu-west-1"
}
}
"""
),
}
},
},
},
};
var response = await client.Send.Message(parameters);
courier send message \
--api-key "$COURIER_API_KEY" \
--message.to '{"phone_number": "+12345678901"}' \
--message.template nt_01kx4h2jdafq8bk9aftxak4b40 \
--message.providers '{"aws-sns": {"override": {"config": {"accessKeyId": "RUNTIME_ACCESS_KEY_ID", "secretAccessKey": "RUNTIME_SECRET_ACCESS_KEY", "region": "eu-west-1"}}}}'
With Courier MCP, send my template to +12345678901 through SNS in a different region.
body override merges into the SNS Publish request, so its fields use AWS parameter names rather than Courier’s. See the SNS publish properties.
const { requestId } = await courier.send.message({
message: {
template: "nt_01kx4h2jdafq8bk9aftxak4b40",
to: {
phone_number: "+12345678901",
},
providers: {
"aws-sns": {
override: {
body: {
MessageAttributes: {
"AWS.SNS.SMS.SMSType": {
DataType: "String",
StringValue: "Transactional",
},
},
},
},
},
},
},
});
response = client.send.message(
message={
"template": "nt_01kx4h2jdafq8bk9aftxak4b40",
"to": {
"phone_number": "+12345678901",
},
"providers": {
"aws-sns": {
"override": {
"body": {
"MessageAttributes": {
"AWS.SNS.SMS.SMSType": {
"DataType": "String",
"StringValue": "Transactional",
},
},
},
},
},
},
},
)
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": {
"phone_number": "+12345678901"
},
"providers": {
"aws-sns": {
"override": {
"body": {
"MessageAttributes": {
"AWS.SNS.SMS.SMSType": {
"DataType": "String",
"StringValue": "Transactional"
}
}
}
}
}
}
}
}'
response = courier.send_.message(
message: {
template: "nt_01kx4h2jdafq8bk9aftxak4b40",
to: {
phone_number: "+12345678901"
},
providers: {
"aws-sns": {
override: {
body: {
MessageAttributes: {
"AWS.SNS.SMS.SMSType": {
DataType: "String",
StringValue: "Transactional"
}
}
}
}
}
}
}
)
response, err := client.Send.Message(context.TODO(), courier.SendMessageParams{
Message: courier.SendMessageParamsMessage{
To: courier.SendMessageParamsMessageToUnion{
OfUserRecipient: &shared.UserRecipientParam{
PhoneNumber: courier.String("+12345678901"),
},
},
Template: courier.String("nt_01kx4h2jdafq8bk9aftxak4b40"),
Providers: shared.MessageProvidersParam{
"aws-sns": shared.MessageProvidersTypeParam{
Override: map[string]any{
"body": map[string]any{
"MessageAttributes": map[string]any{
"AWS.SNS.SMS.SMSType": map[string]any{
"DataType": "String",
"StringValue": "Transactional",
},
},
},
},
},
},
},
})
SendMessageParams params = SendMessageParams.builder()
.message(SendMessageParams.Message.builder()
.to(UserRecipient.builder().phoneNumber("+12345678901").build())
.template("nt_01kx4h2jdafq8bk9aftxak4b40")
.providers(MessageProviders.builder()
.putAdditionalProperty("aws-sns", JsonValue.from(java.util.Map.of("override", java.util.Map.of(
"body", java.util.Map.of(
"MessageAttributes", java.util.Map.of(
"AWS.SNS.SMS.SMSType", java.util.Map.of(
"DataType", "String",
"StringValue", "Transactional"
)
)
)
))))
.build())
.build())
.build();
SendMessageResponse response = client.send().message(params);
$response = $client->send->message(
message: [
'template' => 'nt_01kx4h2jdafq8bk9aftxak4b40',
'to' => [
'phone_number' => '+12345678901',
],
'providers' => [
'aws-sns' => [
'override' => [
'body' => [
'MessageAttributes' => [
'AWS.SNS.SMS.SMSType' => [
'DataType' => 'String',
'StringValue' => 'Transactional',
],
],
],
],
],
],
],
);
SendMessageParams parameters = new()
{
Message = new()
{
To = new UserRecipient { PhoneNumber = "+12345678901" },
Template = "nt_01kx4h2jdafq8bk9aftxak4b40",
Providers = new Dictionary<string, MessageProvidersType>()
{
{
"aws-sns",
new()
{
Override = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(
"""
{
"body": {
"MessageAttributes": {
"AWS.SNS.SMS.SMSType": {
"DataType": "String",
"StringValue": "Transactional"
}
}
}
}
"""
),
}
},
},
},
};
var response = await client.Send.Message(parameters);
courier send message \
--api-key "$COURIER_API_KEY" \
--message.to '{"phone_number": "+12345678901"}' \
--message.template nt_01kx4h2jdafq8bk9aftxak4b40 \
--message.providers '{"aws-sns": {"override": {"body": {"MessageAttributes": {"AWS.SNS.SMS.SMSType": {"DataType": "String", "StringValue": "Transactional"}}}}}}'
With Courier MCP, send my template to +12345678901 with the SNS publish parameters overridden.
Provider details
aws-sns
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.