Send email in Laravel with an email API

How to send transactional email from Laravel — Http facade to Notify, no SMTP mailer required.

Send transactional email from Laravel with the HTTP client from a controller, listener, or queued job. Store the API key in .env — never in Blade. You do not need MAIL_MAILER=smtp for this path.

Prerequisites

  • API key — authenticate every request with the x-api-key header
  • Verified domain — required for production sends from a custom from address
  • Laravel 10+ recommended
# .env
NOTIFY_API_KEY=your_api_key_here
NOTIFY_FROM=noreply@your-verified-domain.com
// config/services.php
'notify' => [
    'key' => env('NOTIFY_API_KEY'),
    'from' => env('NOTIFY_FROM', 'noreply@your-verified-domain.com'),
    'url' => 'https://notify.cx/api/email/send',
],

Service class

<?php
// app/Services/NotifyMailer.php

namespace App\Services;

use Illuminate\Support\Facades\Http;
use RuntimeException;

class NotifyMailer
{
    public function send(string $to, string $subject, string $message, ?string $from = null): array
    {
        $response = Http::withHeaders([
            'x-api-key' => config('services.notify.key'),
            'Content-Type' => 'application/json',
        ])->post(config('services.notify.url'), [
            'from' => $from ?? config('services.notify.from'),
            'to' => $to,
            'subject' => $subject,
            'message' => $message,
        ]);

        if ($response->failed()) {
            throw new RuntimeException(
                'Notify send failed: '.$response->status().' '.$response->body()
            );
        }

        return $response->json() ?? [];
    }
}

Render Blade to a string when you want templates:

$html = view('emails.welcome', ['name' => $user->name])->render();
app(NotifyMailer::class)->send($user->email, 'Welcome', $html);

Controller example

<?php
// app/Http/Controllers/WelcomeEmailController.php

namespace App\Http\Controllers;

use App\Services\NotifyMailer;
use Illuminate\Http\Request;

class WelcomeEmailController extends Controller
{
    public function __invoke(Request $request, NotifyMailer $mailer)
    {
        $data = $request->validate([
            'email' => ['required', 'email'],
            'name' => ['nullable', 'string'],
        ]);

        $name = $data['name'] ?? 'there';
        $mailer->send(
            $data['email'],
            'Welcome',
            "<p>Hi {$name},</p><p>Thanks for signing up.</p>"
        );

        return response()->json(['ok' => true]);
    }
}

Queue it

<?php
// app/Jobs/SendTransactionalEmail.php

namespace App\Jobs;

use App\Services\NotifyMailer;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class SendTransactionalEmail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(
        public string $to,
        public string $subject,
        public string $message,
    ) {}

    public function handle(NotifyMailer $mailer): void
    {
        $mailer->send($this->to, $this->subject, $this->message);
    }
}
SendTransactionalEmail::dispatch(
    $user->email,
    'Reset your password',
    '<p><a href="'.$url.'">Reset password</a></p>'
);

For a minimal PHP sample without Laravel, see the PHP guide.


Where to next?