Skip to content

Email API and SMTP relay / Hosted in Germany

Transactional email that stays in the EU.

Receipts, password resets and alerts, sent from your own domain. Messages, logs and inbound mail are stored on servers in Germany.

Message 48213 / ana@example.com

Deliveredin 1.4 s, over TLS
14:20:01  Accepted by the API
14:20:02  250 2.0.0 OK gmail-smtp-in
14:20:03  email.delivered sent, 200
Authentication-Results:
  dkim=pass header.d=acme.eu
  spf=pass smtp.mailfrom=psrp.acme.eu
  dmarc=pass
List-Unsubscribe-Post: List-Unsubscribe=One-Click

Hosted in Germany (EU)

REST + SMTP 587 / 2525

Standard Webhooks

OpenAPI 3.1

zsender-sdk, 0 dependencies

One pipeline, four jobs

Every send leaves a trail you can read later, line by line.

Send

  • REST API
  • SMTP relay
  • TypeScript SDK
  • Idempotency keys

Verify

  • SPF, DKIM, return path
  • Found vs expected value
  • Subdomain-aware hosts
  • Test keys

Watch

  • SMTP transcripts
  • Spam score with rules
  • Signed webhooks
  • Tags and analytics

Receive

  • Inbound to webhook
  • 30-day message store
  • Raw MIME on request
  • Suppression list

Underneath: one mail server in Germany, Postgres for every event, one error contract with 16 codes.

Why transactional mail goes quiet

Mail rarely fails loudly. It fails in a DNS record, a retry or a bounce nobody reads.

SPF     INVALID
found   v=spf1 include:_spf.google.com
expect  include:spf.zsender.io

The record is there, and wrong.

We show the value we found next to the one we expect, so you fix the right line.

POST /v1/emails/send
Idempotency-Key: rcpt-2041
(timeout, retry)
200, same message, sent once

The timeout that sends twice.

Retry with the same key and the receipt still arrives one time.

email.bounced  ana@exmaple.com
suppressed     HARD_BOUNCE
next send      skipped, listed in response

The bounce nobody hears about.

Hard bounces go on your suppression list, and every later API send lists the recipients it skipped.

What you get

Four things, done carefully.

Domains

Send from your own domain.

Publish the records in one visit to your DNS provider. One check covers sending and receiving, and tells you which line is wrong.

Set up a domain

acme.eu / DNS

TXT @ v=spf1 include:spf.zsender.io ~allVerified
TXT zsender-k3x9qa._domainkeyVerified
CNAME psrp rp.zsender.ioMissing
TXT _dmarc v=DMARC1; p=noneFound

Test mode

Test without sending.

Keys that start with zst_ run the real pipeline and stop before delivery. Your CI can send a hundred receipts and none reach a customer.

How test mode works

Sandbox inbox

Your receipt for OctoberCaptured
Reset your password1 link issue
Welcome to AcmeCaptured
Invoice 2041 overdueCaptured

Observability

Know what happened.

Every message keeps the receiving server's reply, the spam score with the rules behind it, and each event we sent to your webhook.

Read about events

Message 48213

250 2.0.0 OK gmail-smtp-inDelivered
Spam score 0.4Clean
email.opened 14:31Opened
webhook api.acme.eu200

Inbound

Receive mail as JSON.

Point an MX record at us. Each message is stored for 30 days and announced to your endpoints as email.received, signed.

Receive email

email.received

from ana@example.comStored
to support@acme.euRouted
attachments 230 days
POST api.acme.eu/inbound200

Data residency

What stays in the EU.

What we store about the mail you send stays in Germany. The providers outside the EU, and what each one sees, are named in the privacy policy.

Message content, headers, recipients
Germany
Delivery logs, events, webhook payloads
Germany
Inbound mail and attachments, 30 days
Germany
Billing, analytics after consent, network security, internal alerts, the IP lookup at signup
Outside the EU

One key. Your domain. Mail from Germany.

Get an API key

1,000 emails a month free, no card. Pro is $29 a month for 50,000.