An email API that fits your code.
Send transactional and broadcast email with a familiar API. From a single request to the event that follows, keep your email workflow in your application.




Send from
your stack.
Official SDKs for Node.js, Python, PHP, Go, Ruby, Java and .NET, or plain HTTP.
Developersnpm install zapsmtpimport { ZapSMTP } from 'zapsmtp';
const zap = new ZapSMTP(); // reads ZAP_API_KEY, on your server
await zap.emails.send({
from: 'Halden <security@haldenoutfitters.com>',
to: 'sofia.marin@example.com',
template: {
id: 'sign-in-code',
variables: {
name: 'Sofia',
code: '482 913',
expires_in: '10 minutes',
device: 'Safari on iPhone',
location: 'Portland, US',
time: '9:41 AM',
},
},
});from zapsmtp import ZapSMTP
zap = ZapSMTP() # reads ZAP_API_KEY, on your server
zap.emails.send(
from_="Halden <security@haldenoutfitters.com>",
to="sofia.marin@example.com",
template={
"id": "sign-in-code",
"variables": {
"name": "Sofia",
"code": "482 913",
"expires_in": "10 minutes",
"device": "Safari on iPhone",
"location": "Portland, US",
"time": "9:41 AM",
},
},
)<?php
require 'vendor/autoload.php';
$zap = new \ZapSMTP\Client(); // reads ZAP_API_KEY, on your server
$zap->emails->send([
'from' => 'Halden <security@haldenoutfitters.com>',
'to' => 'sofia.marin@example.com',
'template' => ['id' => 'sign-in-code', 'variables' => [
'name' => 'Sofia',
'code' => '482 913',
'expires_in' => '10 minutes',
'device' => 'Safari on iPhone',
'location' => 'Portland, US',
'time' => '9:41 AM',
]],
]);use Illuminate\Mail\Mailable;
use Illuminate\Support\Facades\Mail;
use ZapSMTP\Laravel\Mail\InteractsWithZapSMTP;
class SignInCode extends Mailable
{
use InteractsWithZapSMTP;
public function __construct(array $variables)
{
$this->from('security@haldenoutfitters.com', 'Halden');
$this->zapsmtpTemplate('sign-in-code', $variables);
}
}
// MAIL_MAILER=zapsmtp in .env; then, on your server:
Mail::to('sofia.marin@example.com')->send(new SignInCode([
'name' => 'Sofia',
'code' => '482 913',
'expires_in' => '10 minutes',
'device' => 'Safari on iPhone',
'location' => 'Portland, US',
'time' => '9:41 AM',
]));client := zapsmtp.NewClient("") // "" reads ZAP_API_KEY, on your server
_, err := client.Emails.Send(ctx, &zapsmtp.SendEmailParams{
From: zapsmtp.String("Halden <security@haldenoutfitters.com>"),
To: []string{"sofia.marin@example.com"},
Template: &zapsmtp.TemplateRef{ID: "sign-in-code", Variables: map[string]any{
"name": "Sofia",
"code": "482 913",
"expires_in": "10 minutes",
"device": "Safari on iPhone",
"location": "Portland, US",
"time": "9:41 AM",
}},
})require "zapsmtp"
zap = ZapSMTP::Client.new # reads ZAP_API_KEY, on your server
zap.emails.send(
from: "Halden <security@haldenoutfitters.com>",
to: "sofia.marin@example.com",
template: { id: "sign-in-code", variables: {
name: "Sofia",
code: "482 913",
expires_in: "10 minutes",
device: "Safari on iPhone",
location: "Portland, US",
time: "9:41 AM"
} }
)# config/environments/production.rb
config.action_mailer.delivery_method = :zapsmtp
class SessionMailer < ApplicationMailer
def sign_in_code(variables)
mail(from: "Halden <security@haldenoutfitters.com>", to: "sofia.marin@example.com", body: "", zapsmtp: {
template: { id: "sign-in-code", variables: variables },
subject: nil # use the template's subject
})
end
end
SessionMailer.sign_in_code({
name: "Sofia",
code: "482 913",
expires_in: "10 minutes",
device: "Safari on iPhone",
location: "Portland, US",
time: "9:41 AM"
}).deliver_laterimport com.zapsmtp.ZapSMTP;
import com.zapsmtp.params.SendEmailParams;
import com.zapsmtp.params.TemplateRef;
import java.util.Map;
ZapSMTP zap = ZapSMTP.fromEnv(); // reads ZAP_API_KEY, on your server
zap.emails().send(SendEmailParams.builder()
.from("Halden <security@haldenoutfitters.com>")
.to("sofia.marin@example.com")
.template(TemplateRef.builder().id("sign-in-code").variables(Map.of(
"name", "Sofia",
"code", "482 913",
"expires_in", "10 minutes",
"device", "Safari on iPhone",
"location", "Portland, US",
"time", "9:41 AM"
)).build())
.build());using ZapSMTP;
var zap = new ZapSMTPClient(); // reads ZAP_API_KEY, on your server
await zap.Emails.SendAsync(new SendEmailParams
{
From = "Halden <security@haldenoutfitters.com>",
To = new[] { "sofia.marin@example.com" },
Template = new TemplateRef
{
Id = "sign-in-code",
Variables = new Dictionary<string, object?>
{
["name"] = "Sofia",
["code"] = "482 913",
["expires_in"] = "10 minutes",
["device"] = "Safari on iPhone",
["location"] = "Portland, US",
["time"] = "9:41 AM",
},
},
});Keep content
out of your code.
Design templates in the editor and send one by its ID with your variables.
Templates



A key for
each job.
Test keys run the whole pipeline and never deliver. Live keys can be limited to one domain or stream.
API keys

Follow the event
into your app.
Signed webhooks for every event, with retries, replay and a log of every attempt.
Webhooks

Also included
Batch sending
Up to 100 emails per request, with strict or permissive validation.
Scheduled sending
Prepare email in advance. Cancel or reschedule before it goes out.
Transactional & broadcast streams
Separate streams keep marketing traffic from affecting your password resets.
One-click unsubscribe
RFC 8058 one-click unsubscribe on broadcast email, as Gmail and Yahoo require.
Open & click tracking
Enable tracking per domain. Both are off by default.
Tags & metadata
Attach your own IDs and find them in every event.
Attachments by URL
Attach a file by URL instead of including its content in the request.
Sender name per domain
Set a default display name for each sending domain.
Idempotent requests
Retry an interrupted request without duplicating email sends.
Send your first email.
Your next email starts with a few lines of code.