If you’re currently using Amazon SES and want to migrate to SendPost, we offer Amazon SES Compatible APIs (v1 and v2) that minimize code changes. You only need to change the endpoint URL and replace AWS Signature authentication with a simple API key header.
Quick Migration Steps
Change the endpoint URL
- From:
https://email.{region}.amazonaws.com/
- To:
https://api.sendpost.io/api/v1/subaccount/email/ses/v1
- From:
https://email.{region}.amazonaws.com/v2/email/outbound-emails
- To:
https://api.sendpost.io/api/v1/subaccount/email/ses/v2
Update authentication
- From: AWS Signature Version 4 (complex signing with access/secret keys)
- To:
X-SubAccount-ApiKey: YOUR_SENDPOST_API_KEY header
Keep your request body
Use the exact same SES v1 or v2 JSON request format - no changes needed!
Optional: Add SendPostOptions
Optionally add SendPostOptions to leverage SendPost-specific features like IP Pool routing
SES v1 Migration Example
Before (Amazon SES v1)
After (SendPost SES v1)
curl -X POST "https://email.us-east-1.amazonaws.com/" \
-H "Authorization: AWS4-HMAC-SHA256 Credential=..." \
-H "Content-Type: application/x-amz-json-1.0" \
-d '{
"Source": "sender@example.com",
"Destination": {
"ToAddresses": ["recipient@example.com"]
},
"Message": {
"Subject": {
"Data": "Hello World",
"Charset": "UTF-8"
},
"Body": {
"Text": {
"Data": "Hello!",
"Charset": "UTF-8"
},
"Html": {
"Data": "<p>Hello!</p>",
"Charset": "UTF-8"
}
}
}
}'
curl -X POST "https://api.sendpost.io/api/v1/subaccount/email/ses/v1" \
-H "X-SubAccount-ApiKey: YOUR_SENDPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"Source": "sender@example.com",
"Destination": {
"ToAddresses": ["recipient@example.com"]
},
"Message": {
"Subject": {
"Data": "Hello World",
"Charset": "UTF-8"
},
"Body": {
"Text": {
"Data": "Hello!",
"Charset": "UTF-8"
},
"Html": {
"Data": "<p>Hello!</p>",
"Charset": "UTF-8"
}
}
},
"SendPostOptions": {
"IPPool": "ses-pool"
}
}'
SES v2 Migration Example
Before (Amazon SES v2)
After (SendPost SES v2)
curl -X POST "https://email.us-east-1.amazonaws.com/v2/email/outbound-emails" \
-H "Authorization: AWS4-HMAC-SHA256 Credential=..." \
-H "Content-Type: application/x-amz-json-1.0" \
-d '{
"FromEmailAddress": "sender@example.com",
"Destination": {
"ToAddresses": ["recipient@example.com"]
},
"Content": {
"Simple": {
"Subject": {
"Data": "Hello World",
"Charset": "UTF-8"
},
"Body": {
"Text": {
"Data": "Hello!",
"Charset": "UTF-8"
},
"Html": {
"Data": "<p>Hello!</p>",
"Charset": "UTF-8"
}
}
}
}
}'
curl -X POST "https://api.sendpost.io/api/v1/subaccount/email/ses/v2" \
-H "X-SubAccount-ApiKey: YOUR_SENDPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"FromEmailAddress": "sender@example.com",
"Destination": {
"ToAddresses": ["recipient@example.com"]
},
"Content": {
"Simple": {
"Subject": {
"Data": "Hello World",
"Charset": "UTF-8"
},
"Body": {
"Text": {
"Data": "Hello!",
"Charset": "UTF-8"
},
"Html": {
"Data": "<p>Hello!</p>",
"Charset": "UTF-8"
}
}
}
},
"SendPostOptions": {
"IPPool": "ses-pool"
}
}'
Field Mappings
SES v1 → SendPost
| SES v1 Field | SendPost Field | Notes |
|---|
Source | From.Email, From.Name | Supports “Name <email>” format |
Destination.ToAddresses[] | To[].Email | Direct mapping |
Destination.CcAddresses[] | To[].Cc[] | Direct mapping |
Destination.BccAddresses[] | To[].Bcc[] | Direct mapping |
Message.Subject.Data | Subject | Direct mapping |
Message.Body.Text.Data | TextBody | Direct mapping |
Message.Body.Html.Data | HtmlBody | Direct mapping |
ReplyToAddresses[] | ReplyTo.Email | First address only |
Tags[] | Groups[] | Formatted as “Name:Value” |
SendPostOptions.IPPool | IPPool | SendPost extension |
SendPostOptions.TrackOpens | TrackOpens | SendPost extension |
SendPostOptions.TrackClicks | TrackClicks | SendPost extension |
SendPostOptions.WebhookEndpoint | WebhookEndpoint | SendPost extension |
SES v2 → SendPost
| SES v2 Field | SendPost Field | Notes |
|---|
FromEmailAddress | From.Email, From.Name | Supports “Name <email>” format |
Destination.ToAddresses[] | To[].Email | Direct mapping |
Destination.CcAddresses[] | To[].Cc[] | Direct mapping |
Destination.BccAddresses[] | To[].Bcc[] | Direct mapping |
Content.Simple.Subject.Data | Subject | Only Simple content type supported |
Content.Simple.Body.Text.Data | TextBody | Direct mapping |
Content.Simple.Body.Html.Data | HtmlBody | Direct mapping |
ReplyToAddresses[] | ReplyTo.Email | First address only |
EmailTags[] | Groups[] | Formatted as “Name:Value” |
SendPostOptions.IPPool | IPPool | SendPost extension |
SendPostOptions.TrackOpens | TrackOpens | SendPost extension |
SendPostOptions.TrackClicks | TrackClicks | SendPost extension |
SendPostOptions.WebhookEndpoint | WebhookEndpoint | SendPost extension |
SendPostOptions Extension
SendPost offers optional extensions through the SendPostOptions field that are not available in the standard SES API:
{
"SendPostOptions": {
"IPPool": "ses-pool", // IP pool name for routing
"TrackOpens": true, // Enable open tracking
"TrackClicks": true, // Enable click tracking
"WebhookEndpoint": "https://..." // Webhook URL for events
}
}
Tracking Explained: Open and click events are tracked via Amazon SES’s configuration set (“sendpost-events”) and delivered to SendPost through SNS notifications. The TrackOpens and TrackClicks options in SendPostOptions control SendPost’s tracking pixels, which provide additional tracking when emails are processed by SendPost before being sent to SES. Both tracking methods work independently.
Supported SES Features
| Feature | SES v1 | SES v2 | Notes |
|---|
Source / FromEmailAddress | ✅ | ✅ | Supports “Name <email>” format |
Destination.ToAddresses | ✅ | ✅ | Direct mapping |
Destination.CcAddresses | ✅ | ✅ | Direct mapping |
Destination.BccAddresses | ✅ | ✅ | Direct mapping |
Message.Subject / Content.Simple.Subject | ✅ | ✅ | Direct mapping |
Message.Body.Text / Content.Simple.Body.Text | ✅ | ✅ | Direct mapping |
Message.Body.Html / Content.Simple.Body.Html | ✅ | ✅ | Direct mapping |
ReplyToAddresses | ✅ | ✅ | First address only |
Tags / EmailTags | ✅ | ✅ | Mapped to Groups as “Name:Value” |
SendPostOptions | ✅ | ✅ | SendPost extension |
Unsupported SES Features
The following SES features are not supported and will return a ValidationException error if present:
| Feature | Alternative |
|---|
RawMessage (v1) | Use Message with Subject and Body instead |
Content.Raw (v2) | Use Content.Simple instead |
Template, TemplateData, TemplateArn (v1) | Use SendPost’s native template API or include content directly |
Content.Template (v2) | Use SendPost’s native template API or include content directly |
SourceArn, ReturnPath, ReturnPathArn (v1) | Handled automatically by SendPost |
FromEmailAddressIdentityArn (v2) | Not needed with SendPost |
FeedbackForwardingEmailAddress (v2) | Handled automatically by SendPost |
ListManagementOptions (v2) | Use SendPost’s {{unsubscribe}} template variable |
Error Response for Unsupported Fields:
{
"__type": "ValidationException",
"message": "Field 'RawMessage' is not supported. Please use Message with Subject and Body instead."
}
Success Response (HTTP 200)
{
"MessageId": "550e8400-e29b-41d4-a716-446655440000"
}
Error Response (HTTP 400/403/413/429/500)
{
"__type": "ValidationException",
"message": "1 validation error detected: Value at 'Source' failed to satisfy constraint: Member must satisfy regular expression pattern: [\\u0020-\\u007E]+"
}
Error Types
| Error Type | HTTP Status | Description |
|---|
ValidationException | 400 | Invalid request format or missing required fields |
AccessDeniedException | 403 | Invalid or missing API key |
MessageRejected | 400 | Email rejected (e.g., domain not verified) |
MailFromDomainNotVerifiedException | 400 | Domain not verified in SendPost |
MessageTooLarge | 413 | Payload exceeds 10MB limit |
TooManyRequestsException | 429 | Rate limit exceeded |
ServiceException | 500 | Internal server error |
Key Differences: SES v1 vs v2
| Feature | SES v1 | SES v2 |
|---|
| Source field | Source | FromEmailAddress |
| Subject | Message.Subject | Content.Simple.Subject |
| Body | Message.Body | Content.Simple.Body |
| Tags | Tags[] | EmailTags[] |
| Content types | Simple only | Simple, Raw, Template (only Simple supported) |
IP Pool Routing
When using the Amazon SES Compatible API, you can specify an IP Pool through SendPostOptions.IPPool. This IP Pool must be configured in SendPost to route traffic to your Amazon SES provider.
Important: The IP Pool specified in SendPostOptions.IPPool must exist in SendPost and be configured to route to your Amazon SES provider. If not specified, the default IP Pool will be used.
Next Steps