Email Fast Get a sandbox key
Guides

Send email with PHP

Bundled cURL, one JSON POST, a message id back — no Composer package required.

Facts verified 2026-07-17 — corrections: hello@emailfast.dev

PHP needs nothing beyond the bundled cURL extension — the Email Fast API is one JSON POST with a bearer token. Unlike mail(), you get a message id back, with a full event timeline behind it. If you want a typed client instead, the PHP SDK quickstart covers that.

<?php
// send.php — PHP 8+, ext-curl (bundled)

$payload = json_encode([
    "to" => "ada@example.com",
    "subject" => "Welcome",
    "html" => "<h1>Hi {{name}}</h1>",
    "data" => ["name" => "Ada"],
    "idempotency_key" => "welcome-ada-1", // a retry replays, never re-sends
]);

$ch = curl_init("https://api.emailfast.dev/v1/emails");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $payload,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 10,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("EMAILFAST_API_KEY"), // ef_sandbox_... while testing
        "Content-Type: application/json",
    ],
]);

$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);

if ($body === false || $status >= 400) {
    throw new RuntimeException("Send rejected ($status): $body");
}

$result = json_decode($body, true);
echo $result["id"] . " " . $result["status"]; // msg_... queued

a 202 from the API means the send is committed to a durable, partitioned outbox before we answer — a crash can't lose it, and a retry with the same idempotency key can't double-send.

Gotchas

Next

See it for yourself

Sandbox keys run the real pipeline dry — real validation, real events, a hosted inbox, no email sent. Early access is onboarding now.