Send emails with ASP.NET
Transactional and marketing email from a minimal API, controller, or BackgroundService. One HttpClient call returns an id you can trace.
✓Free to start. Unlimited contacts on every tier.
One request, complete trace
Request
POST /api/v1/emails
Authorization: Bearer aem_…
Idempotency-Key: welcome-8f21
{ "to": "[email protected]", "template": "welcome" }
202 Accepted
{ "id": "msg_7ca31", "status": "queued" }
[ 01 / 05 ]Quickstart
How do I send email from ASP.NET?
Create a key, keep it on the server, and call one endpoint from a minimal API, controller, or BackgroundService.
Get an API key
Open Settings → API & MCP and create a key with the Send + manage permission (the default). It starts with aem_ and is shown once.
Store it as a server-side environment variable
Use user secrets locally and the SendAndRetain__ApiKey environment variable in production. Read it from IConfiguration, and never ship it to Blazor WebAssembly.
Terminaldotnet user-secrets set "SendAndRetain:ApiKey" "aem_…"Send the email
Here http is an injected HttpClient and config is IConfiguration. EnsureSuccessStatusCode throws on a 4xx or 5xx, and a retry with the same Idempotency-Key won't send a second email.
EmailService.csvar apiKey = config["SendAndRetain:ApiKey"]; using var request = new HttpRequestMessage(HttpMethod.Post, "https://sendandretain.com/api/v1/emails"); request.Headers.Authorization = new("Bearer", apiKey); request.Headers.Add("Idempotency-Key", $"welcome-{user.Id}"); request.Content = JsonContent.Create(new { to = user.Email, template = "welcome" }); using var response = await http.SendAsync(request); response.EnsureSuccessStatusCode();Check the response
A 202 means queued, not delivered. Keep the id, then follow delivery in the message log or through a signed webhook.
202 Accepted{ "id": "msg_7ca31", "status": "queued" }
[ 02 / 05 ]Where it goes
Where should email code live in your ASP.NET app?
Minimal APIs, controllers, and hosted services
Call from a controller for immediate work, or a BackgroundService for work outside the request.
Events from the service
Send signup, trial, and payment events from the service that saves them, so automations react to real state.
A raw body for webhooks
A minimal API endpoint reads HttpRequest.Body before model binding.
[ 03 / 05 ]Marketing email
Can I send marketing emails from ASP.NET too?
Yes. Send an event from the same service when a user signs up, starts a trial, or goes quiet, and an automation sends the right email. Automations start paused, and every email goes to one person: no newsletter blasts.
- Transactional and marketing email share one contact record and one unsubscribe list.
- Unsubscribes, bounces, and complaints are suppressed for you before every send.
- Templates are react.email components; published versions never change under you.
[ 04 / 05 ]Example prompts
What can you ask your coding agent to do in ASP.NET?
Claude Code, Cursor, and Codex can do these over the Send & Retain MCP server, with your repo open. Automations they build stay paused until you turn them on.
Welcome email
“Add a welcome email to our ASP.NET signup endpoint using Send & Retain, with an idempotency key.”
Typed client
“Register a typed HttpClient for Send & Retain and use it from our order service to send receipts.”
Webhook
“Add a minimal API endpoint that verifies Send & Retain delivery webhooks and marks bounced users.”
Trial automation
“Send a trial_started event from our ASP.NET app and build a paused trial-conversion automation for it.”
[ 05 / 05 ]Related
Keep building with ASP.NET
Questions people ask us
Send your first email from ASP.NET today.
Create a key, paste the code into a minimal API, controller, or BackgroundService, and watch the email land in the message log.