Every dashboard action is an MCP tool your agent can call.Read the docs

Send emails with Spring Boot

Transactional and marketing email from a Spring service, with Spring's RestClient. One call returns an id you can trace.

✓Free to start. Unlimited contacts on every tier.

Server quickstart
Spring Boot

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" }

RuntimeServer process
RequestPOST /api/v1/emails
Result202 · queued
Credentials stay server-side

[ 01 / 05 ]Quickstart

How do I send email from Spring Boot?

Create a key, keep it on the server, and call one endpoint from a Spring service.

  1. 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.

  2. Store it as a server-side environment variable

    Set AEM_KEY=aem_… in the environment and inject it with @Value("${sendandretain.api-key}"). Never commit the key itself.

    application.properties
    sendandretain.api-key=${AEM_KEY}
  3. Send the email

    A service posts with Spring's RestClient, built from the injected RestClient.Builder. retrieve() throws on a 4xx or 5xx, and a retried job that reuses the Idempotency-Key won't send twice.

    EmailService.java
    @Value("${sendandretain.api-key}")
    private String apiKey;
    
    public Map<?, ?> sendWelcome(User user) {
      return restClient.post()
          .uri("https://sendandretain.com/api/v1/emails")
          .header("Authorization", "Bearer " + apiKey)
          .header("Idempotency-Key", "welcome-" + user.id())
          .contentType(MediaType.APPLICATION_JSON)
          .body(Map.of("to", user.email(), "template", "welcome"))
          .retrieve()
          .body(Map.class);
    }
  4. 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 Spring Boot app?

Services, events, and scheduled jobs

A service owns the call. @Async moves it off the request thread; a durable worker survives restarts.

Events after commit

Send events after the transaction commits, so automations never act on a change that rolled back.

A raw body for webhooks

A @RestController takes the body as a String, so the signature is checked over the exact bytes.

[ 03 / 05 ]Marketing email

Can I send marketing emails from Spring Boot 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 Spring Boot?

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 Spring Boot signup service using Send & Retain, with an idempotency key.”

  • After commit

    “Send our order confirmation email from a @TransactionalEventListener so it only goes out after the commit.”

  • Webhook

    “Add a Spring controller that verifies Send & Retain delivery webhooks and marks bounced users.”

  • Trial automation

    “Send a trial_started event from our Spring Boot service and build a paused trial-conversion automation for it.”

Questions people ask us

Send your first email from Spring Boot today.

Create a key, paste the code into a Spring service, and watch the email land in the message log.