Keep your Resend code. Send through your own Amazon account.
Change two settings, and the app you have sends through mails.ai and out through Amazon SES in your own AWS account, at Amazon’s price. It goes on your AWS bill, where AWS credits can pay for it.
mails.ai answers the calls Resend’s SDKs make to send an email, send a batch and read an email back. Point your SDK at it and connect the Amazon SES account in your own AWS account, and your mail goes out through that account. Amazon bills you for it at its own price, and your mails.ai plan covers the API, the logs, and the bounces, complaints and suppression list.
Two settings, no code changes
Your Resend key becomes a mails.ai key, and the SDK’s base URL points at mails.ai. Set both where your app reads its environment, before it starts:
# .env: the two settings that change
# your mails.ai API key
RESEND_API_KEY= mk_live_…
# where the SDK sends its calls
RESEND_BASE_URL= https://api.mails.ai/resend# .env: the two settings that change
# your mails.ai API key
RESEND_API_KEY= mk_live_…
# where the SDK sends its calls
RESEND_API_URL= https://api.mails.ai/resendThe code you have stays as it is:
import { Resend } from "resend";
const resend = new Resend( process. env. RESEND_API_KEY);
const { data, error } = await resend. emails. send({
from: "Acme <hello@acme.com>" ,
to: [ "customer@example.com" ],
subject: "Your receipt",
html: "<p>Thanks for your order.</p>",
});import os
# reads RESEND_API_URL when imported
import resend
resend. api_key = os. environ[ "RESEND_API_KEY"]
email = resend. Emails. send({
"from": "Acme <hello@acme.com>" ,
"to": [ "customer@example.com" ],
"subject": "Your receipt",
"html": "<p>Thanks for your order.</p>",
})Go, Ruby and PHP read a base URL the same way. Go and Ruby add the path to it without a slash of their own, so their value ends in one:
| SDK | Setting | Value |
|---|---|---|
| Node.js | RESEND_BASE_URL | https://api.mails.ai/ |
| Python | RESEND_API_URL | https://api.mails.ai/ |
| Go | RESEND_BASE_URL | https://api.mails.ai/ |
| Ruby | RESEND_BASE_URL | https://api.mails.ai/ |
| PHP | RESEND_BASE_URL | https://api.mails.ai/ |
The key is a mails.ai API key (mk_live_…) from your dashboard; a Resend key does not work here. For a send to go out through your Amazon SES, its from domain must be verified there; How it works covers connecting the account.
What it costs
Resend charges by plan. Amazon charges $0.16 per 1,000 emails on its Essentials plan, the one a new SES account starts on. Sending through your own account comes with mails.ai’s paid plans at no extra charge: Pro ($20 a month) sends up to 200,000 emails a month through it, and Scale ($99) up to 2,500,000.
Up to 100,000 emails a month, Resend’s Free and Pro plans cost less than Amazon plus a mails.ai plan, so staying is the cheaper choice. From 200,000 a month this costs less, and the gap grows with your volume.
Resend’s prices are the ones its pricing page showed on October 21, 2026, at the least each volume costs there. At 200,000 that is Pro with pay-as-you-go extra emails, $0.90 per 1,000 past its 100,000, which costs less than Scale. Amazon’s is its Essentials price per email, before what it charges for attachment data and any other SES feature you turn on.
Because Amazon bills the sending to your own AWS account, AWS promotional credits can pay for it. Each grant names the services it covers, so check that yours includes SES. Your mails.ai plan is billed by mails.ai, and credits do not pay for it.
What carries over
emails.sendwithfrom,to,cc,bcc, onereply_to,subject,html,text,attachments,tagsandscheduled_at, and an idempotency key.batch.send: up to 100 emails a call, with Resend’s strict and permissive validation, and no attachments, as on Resend.emails.get: the email in Resend’s shape, with its last event.- Errors in Resend’s shape and with Resend’s names for them, and mails.ai’s own error beside each one.
What does not:
- Stored templates and topics.
- Custom headers other than
In-Reply-ToandReferences.X-Entity-Ref-IDis dropped. - Listing, updating and cancelling emails, and Resend’s domains, contacts and broadcasts APIs: those calls answer Resend’s 404.
Two things work differently. Each from address is an agent in your mails.ai workspace, made by the first email it sends with a full-access key. And unless you set reply_to, mails.ai points the Reply-To at the agent, so replies reach you as reply.received events. The compatibility page has every field, answer and error.
How it works
- Create one IAM role in your AWS account.
POST /v1/ses-connection/setupanswers with its trust policy and its permissions policy, filled in for your workspace. - Connect it with
POST /v1/ses-connection, naming the role and the SES region you send from. mails.ai checks the role, then makes a configuration set and an SNS topic in your account for the bounce, complaint and delivery reports. - Send. Mail from a domain verified in that region goes out through your account. mails.ai’s rules still refuse prohibited content, phishing links and plainly cold or bulk mail, and each agent’s limits apply. Amazon reports each bounce and complaint back, and the address goes on your suppression list.
Mail from your mails.ai addresses goes out as before. Connecting is done with the API for now: there is no screen for it in the dashboard yet. The setup guide takes you through it.
FAQ
Questions before you connect an account
Why a role, and not access keys?
How do I take that access away?
DELETE /v1/ses-connection: mails.ai stops sending through your account at once, and removes the configuration set and SNS topic it made there while the role still lets it. Or end it from AWS, by deleting the role or taking mails.ai out of its trust policy. mails.ai keeps the role’s temporary credentials for up to an hour, so a trust policy change holds from the next time it asks for new ones.What happens to bounces and complaints?
message.bounced or message.complained as you would for any send. Nothing goes out through your account until SNS has confirmed that subscription.What about the SES sandbox?
POST /v1/ses-connection/test shows whether yours is still there (account.sandbox). While it is, Amazon refuses mail to anyone else, and the send answers 422 ses_message_rejected with Amazon’s reason. Production access is something you ask Amazon for, in the SES console.Can AWS credits pay for the sending?
Which mail goes out through my account?
Is there a screen for this in the dashboard?
Related
What to read next
Keep your code, change where it sends
Choose Pro or Scale, connect your Amazon SES account, and set two settings.
Get your API key