Send transactional emails from AWS Lambda using Lettr’s HTTP API. Lambda’s event-driven architecture pairs perfectly with Lettr — no persistent connections, no background workers, just simple HTTP requests.
Using Cursor? Jump straight in using this prompt
Prerequisites
Before you begin, make sure you have:
API Key Create an API key in the Lettr dashboard
Verified Domain Add and verify your sending domain
You’ll also need:
AWS account with Lambda access and appropriate IAM permissions
Node.js 18.x or 20.x runtime
AWS CLI installed and configured (optional, but recommended)
Quick Setup
Create a Lambda function
Create a new Lambda function in the AWS Console or via AWS CLI: aws lambda create-function \
--function-name send-email \
--runtime nodejs20.x \
--role arn:aws:iam::YOUR_ACCOUNT_ID:role/lambda-execution-role \
--handler index.handler \
--zip-file fileb://function.zip
Add environment variables
Set your Lettr API key as an environment variable: aws lambda update-function-configuration \
--function-name send-email \
--environment "Variables={LETTR_API_KEY=lttr_your_api_key_here,FROM_EMAIL=noreply@yourdomain.com}"
For production, use AWS Secrets Manager instead of environment variables. See the Advanced Guide for details.
Deploy your function
Deploy the function code (see examples below) and test it: aws lambda invoke \
--function-name send-email \
--payload '{"body":"{\"to\":\"user@example.com\",\"subject\":\"Test\",\"html\":\"<p>Hello!</p>\"}"}' \
response.json
Node.js Implementation
Install the SDK in your Lambda function:
Then create your handler:
import { Lettr } from 'lettr' ;
const lettr = new Lettr ( process . env . LETTR_API_KEY );
export const handler = async ( event ) => {
try {
// Parse request body (API Gateway proxy integration)
const body = JSON . parse ( event . body || '{}' );
const { to , subject , html , text } = body ;
// Validate required fields
if ( ! to || ! subject || ( ! html && ! text )) {
return {
statusCode: 400 ,
body: JSON . stringify ({
error: 'Missing required fields: to, subject, and html or text' ,
}),
};
}
// Send email via Lettr
const result = await lettr . emails . send ({
from: process . env . FROM_EMAIL || 'noreply@yourdomain.com' ,
to: Array . isArray ( to ) ? to : [ to ],
subject ,
html ,
text ,
});
console . log ( `Email sent successfully. Request ID: ${ result . request_id } ` );
return {
statusCode: 200 ,
headers: {
'Content-Type' : 'application/json' ,
},
body: JSON . stringify ({
success: true ,
requestId: result . request_id ,
accepted: result . accepted ,
}),
};
} catch ( error ) {
console . error ( 'Failed to send email:' , error );
return {
statusCode: error . status || 500 ,
body: JSON . stringify ({
error: error . message || 'Internal server error' ,
}),
};
}
};
The Lettr SDK automatically handles retries for transient failures and provides better error messages than raw fetch calls.
What’s Next
Advanced Guide Learn about deployment strategies, event triggers, and best practices
Vercel Functions Deploy on Vercel
Cloudflare Workers Deploy on Cloudflare
API Reference Complete API documentation