AWS Messaging & Targeting Blog
Automating Sender ID Configuration for SMS with AWS End User Messaging APIs
Global SMS messaging with consistent Sender ID branding requires configuring the same Sender ID across multiple countries, which is a time-consuming process for businesses operating internationally. In this post, we’ll show you how to automate the configuration of Sender IDs for countries that do not have registration requirements using the AWS End User Messaging v2 API.
The Challenge of Multi-Country Sender ID Configuration
When sending SMS messages internationally, if you are using Sender ID, you want your brand to be consistently recognized. This means configuring the same Sender ID in each country you send to. However there are several challenges related to this:
- Each country must be done manually, one at a time, if using the AWS Console
- If you have multiple environments for testing the process must be repeated for each Account/Region
- If you are moving account/regions you have to reconfigure each country in the new Account/Region
- Manual configuration can be error prone
- Errors can be detrimental to a brand
The Solution: AWS Lambda Automation
This solution can be applied to any country that supports Sender ID configurations and does not require registration. You can view a comprehensive list of these eligible countries here.
Below is an AWS Lambda function that streamlines this process by handling bulk configuration requests. The function solves the challenges in handling multiple country configurations in a single automated workflow. Here’s the complete code:
import boto3
import uuid
import json
import time
from typing import Dict, Any, List
def validate_input(sender_id: str, countries: List[str]) -> bool:
if not 1 <= len(sender_id) <= 11:
raise ValueError("Sender ID must be between 1 and 11 characters")
if not sender_id.replace('_', '').replace('-', '').isalnum():
raise ValueError("Sender ID can only contain alphanumeric characters, underscore, and hyphen")
if not countries:
raise ValueError("At least one country code must be provided")
return True
def request_sender_id(client, sender_id: str, countries: List[str], message_types: List[str] = None, tags: List[Dict] = None) -> List[Dict]:
if message_types is None:
message_types = ["TRANSACTIONAL", "PROMOTIONAL"]
results = []
for i, country in enumerate(countries):
if i > 0:
time.sleep(1) # Rate limiting: 1 request per second
try:
print(f"Processing country: {country} ({i+1}/{len(countries)})")
request_params = {
'ClientToken': str(uuid.uuid4()),
'SenderId': sender_id,
'IsoCountryCode': country.upper(),
'MessageTypes': message_types,
'DeletionProtectionEnabled':True
}
if tags:
request_params['Tags'] = tags
response = client.request_sender_id(**request_params)
results.append({
'Country': country,
'Status': 'Success',
'SenderIdArn': response.get('SenderIdArn'),
'MonthlyLeasingPrice': response.get('MonthlyLeasingPrice')
})
except Exception as e:
results.append({
'Country': country,
'Status': 'Failed',
'Error': str(e)
})
print(f"Completed {country}: {'Success' if results[-1]['Status'] == 'Success' else 'Failed'}")
return results
def lambda_handler(event: Dict[str, Any], context: Any) -> Dict[str, Any]:
try:
# Extract parameters from event
sender_id = event['sender_id']
countries = [c.strip().upper() for c in event['countries'] if c.strip()]
tags = event.get('tags') # Optional
message_types = event.get('message_types', ["TRANSACTIONAL", "PROMOTIONAL"]) # Optional
# Validate input
validate_input(sender_id, countries)
# Initialize the AWS SMS Voice v2 client
client = boto3.client('pinpoint-sms-voice-v2')
# Process the request
results = request_sender_id(
client=client,
sender_id=sender_id,
countries=countries,
message_types=message_types,
tags=tags
)
# Calculate summary
successful = sum(1 for r in results if r['Status'] == 'Success')
return {
'statusCode': 200,
'body': {
'results': results,
'summary': {
'total': len(countries),
'successful': successful,
'failed': len(countries) - successful
}
}
}
except Exception as e:
return {
'statusCode': 500,
'body': {
'error': str(e)
}
}
How the Lambda Function Works to Configure Sender IDs
The Lambda function automates the Sender ID configuration process through these key steps:
- Input Validation: Ensures the Sender ID meets format requirements (1-11 alphanumeric characters, with optional underscores or hyphens).
- Bulk Registration: Processes each country sequentially with built-in rate limiting (1 request per second) to prevent API throttling.
- Logging: Returns the full ARN of each successfully configured Sender ID
- Flexible Configuration Settings:
- Supports multiple message types (transactional, promotional, or both)
- Enables resource tagging for organizational and cost tracking
- Provides deletion protection to prevent accidental removal
- Cost Transparency: Displays monthly leasing price for each successful country configuration
- Error Handling: Individual country failures don’t halt the entire process, allowing partial success if a single country were to fail for some reason.
Using the Lambda Function
To use this function, create a Lambda with the code above and configure an event. The tags are optional and we have provided an example below:
NOTE: Depending on the number of countries you are attempting to register at a time, you may need to increase the 3 second default Lambda timeout. For reference, in our testing, we were able to do all Sender IDs(160) in less than 3 minutes.
Test Event Example
{
"sender_id": "YourBrand",
"countries": ["GB", "DE", "FR"],
"tags": [
{
"Key": "Environment",
"Value": "Production"
},
{
"Key": "Department",
"Value": "Marketing"
}
]
}
IAM Permissions
Your Lambda will need these minimum AWS Identity and Access Management (IAM) permissions, scale back the resource if necessary:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sms-voice:RequestSenderId",
"sms-voice:TagResource"
],
"Resource": "arn:aws:sms-voice:*:**ACCOUNT#**:sender-id/*"
}
]
}
The Trust Policy required for Lambda to assume the role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Results Example
The Lambda will return results for each country, including configuration status and monthly costs, if any. Below you will see an example of 3 countries being configured:
{
"statusCode": 200,
"body": {
"results": [
{
"Country": "GB",
"Status": "Success",
"SenderIdArn": "arn:aws:sms-voice:us-west-2:**ACCOUNT#**:sender-id/LAMBDATEST2/GB",
"MonthlyLeasingPrice": "0.00"
},
{
"Country": "DE",
"Status": "Success",
"SenderIdArn": "arn:aws:sms-voice:us-west-2:**ACCOUNT#**:sender-id/LAMBDATEST2/DE",
"MonthlyLeasingPrice": "0.00"
},
{
"Country": "FR",
"Status": "Success",
"SenderIdArn": "arn:aws:sms-voice:us-west-2:**ACCOUNT#**:sender-id/LAMBDATEST2/FR",
"MonthlyLeasingPrice": "0.00"
}
],
"summary": {
"total": 3,
"successful": 3,
"failed": 0
}
}
}
Function Logs:
START RequestId: 81d2d144-9023-413d-b976-c87c79a82eae Version: $LATEST
Processing country: GB (1/3)
Completed GB: Success
Processing country: DE (2/3)
Completed DE: Success
Processing country: FR (3/3)
Completed FR: Success
After processing your Sender ID configurations, it’s crucial to verify them. You can do this via the AWS console or by using the DescribeSenderIds API. This API offers flexible retrieval options:
- Specify individual Sender IDs for targeted information
- Providing an invalid Sender ID will result in an error
- Apply filters to narrow your results
- Retrieve all Sender IDs associated with your AWS account by omitting both
Conclusion
Automating Sender ID configuration with the AWS End User Messaging v2 API and a Lambda function will dramatically reduce the time spent on manual configuration, ensure consistent branding across all supported and configured countries, and simplify a complex process. You’ll gain a scalable, reliable solution that allows you to deploy and manage your Sender IDs with confidence.
Additional resources: