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

Send emails with Laravel

Transactional and marketing email from a Laravel job or controller. One HTTP call, and retries never send twice.

✓Free to start. Unlimited contacts on every tier.

Server quickstart
Laravel

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 Laravel?

Create a key, keep it on the server, and call one endpoint from a queued job or controller.

  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

    Add AEM_KEY=aem_… to .env on every server that sends, then map it in config/services.php. Your code reads it with config('services.sendandretain.key').

    config/services.php
    'sendandretain' => [
        'key' => env('AEM_KEY'),
    ],
  3. Send the email

    Laravel's HTTP client posts to the email API, and throw() raises on a 4xx or 5xx. A retried job that reuses the same Idempotency-Key won't send a second email.

    send-welcome.php
    use Illuminate\Support\Facades\Http;
    
    $result = Http::withToken(config('services.sendandretain.key'))
      ->withHeaders(['Idempotency-Key' => "welcome-{$user->id}"])
      ->post('https://sendandretain.com/api/v1/emails', [
        'to' => $user->email, 'template' => 'welcome',
      ])->throw()->json();
  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 Laravel app?

Jobs, notifications, and controllers

Dispatch after the database change commits, and let your queue retry with the same key.

Events from listeners

Turn domain events and listeners into automation triggers, instead of scattering follow-up sends across controllers.

A raw body for webhooks

Exclude the route from CSRF middleware and read $request->getContent() raw.

[ 03 / 05 ]Marketing email

Can I send marketing emails from Laravel too?

Yes. Send an event from the same job or listener 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 Laravel?

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 Laravel registration using Send & Retain, with an idempotency key.”

  • Queued job

    “Move our order confirmation email into a queued Laravel job that calls Send & Retain after the transaction commits.”

  • Webhook

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

  • Trial automation

    “Send a trial_started event from our Laravel app and build a paused trial-conversion automation for it.”

Questions people ask us

Send your first email from Laravel today.

Create a key, paste the code into a queued job or controller, and watch the email land in the message log.