$ features

Everything a transactional email needs. Nothing it doesn't.

Pharos does one job: get a receipt, a password reset or an alert from your application into somebody's inbox. Every capability below exists to serve that, and every one of them is on every plan.

01 Two ways in, one pipeline

Post JSON from new code, or point an existing mailer at the relay. They are not two products with different behaviour — the same queue, the same signing, the same alignment checks, the same event log.

REST send APIPOST /v1/send
curl -X POST https://api.pharos.email/v1/send \
  -H "Authorization: Bearer $PHAROS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "receipts@yourapp.com",
    "to": "customer@example.com",
    "subject": "Your receipt from Acme",
    "html": "<p>Thanks for your order.</p>"
  }'
Attachments, reply-to, cc/bcc, per-message tags, custom headers
SMTP relaysmtp.pharosinfra.net:587
# change the host, change nothing else
MAIL_HOST=smtp.pharosinfra.net
MAIL_PORT=587
MAIL_ENCRYPTION=tls
MAIL_USERNAME=$PHAROS_SMTP_USER
MAIL_PASSWORD=$PHAROS_SMTP_PASS

# 250 2.0.0 Ok — signed, aligned, queued
Works with Laravel, Rails, Django, WordPress, n8n, cron
  • idempotent

    A retried request with the same key sends once. A network timeout never doubles a receipt.

  • no SDK required

    Plain HTTP and plain SMTP. Nothing to install, nothing to keep up to date, nothing to audit.

  • same events either way

    An SMTP send produces the same webhooks and the same log entries as an API send.

02 Sender domains

Add a domain, add four records, and Pharos verifies every one before it will send from it. Verified domains are re-checked daily, because a DKIM key that was correct in March is not evidence about today.

  • As many domains and subdomains as you need, on every plan
  • Separate API keys and webhooks per domain
  • A domain that fails verification cannot send — no silent unsigned mail
receipts.yourapp.com VERIFIED
  • TXT v=spf1 include:pharosinfra.net ~all SPF OK
  • TXT ph1._domainkey v=DKIM1; k=rsa; p=MIIBIj… DKIM OK
  • TXT _dmarc v=DMARC1; p=quarantine; adkim=s ALIGNED
  • CNAME bounce → bounce.pharosinfra.net RETURN-PATH
last checked 4 minutes ago · next check in 24h
order-receiptv4 · live
Subject: Your receipt from {{ company }}

Hi {{ first_name }},

Order {{ order_id }} is confirmed.
Total: {{ total }}

{% if tracking_url %}
Track it: {{ tracking_url }}
{% endif %}
v4 · livev3 · 12 Augv2 · 3 Julv1 · 20 Jun

03 Templates

Keep the copy out of your codebase. Send a template name and a set of variables instead of a rendered body, and change the wording without shipping a release.

  • Versioned — every edit is a new version, and you can roll back
  • Variables and conditionals, so one template covers the variants
  • Preview against real variable values before it goes live
  • Plain-text alternative generated alongside the HTML

04 Events, webhooks and the log

Every message produces the same event stream whether you sent it over the API or the relay. Read it in the dashboard, or have it posted to your endpoint and verify the signature.

Event typesidentical on API and SMTP
  • delivered The receiving server accepted the message.
  • bounced It refused, with its own reason code attached.
  • complained The recipient marked it as spam.
  • deferred Temporarily rejected; Pharos retries on a backoff.
  • opened Tracking pixel loaded, where tracking is on.
  • clicked A tracked link in the message was followed.
Verify the signaturenode
// every webhook carries a signature header
const expected = crypto
  .createHmac("sha256", PHAROS_WEBHOOK_SECRET)
  .update(rawBody)
  .digest("hex");

if (!crypto.timingSafeEqual(
      Buffer.from(expected),
      Buffer.from(req.headers["x-pharos-signature"])
    )) return res.status(401).end();
Retried with backoff until your endpoint returns 2xx

05 Suppression

A hard bounce or a spam complaint adds that address to your suppression list, and Pharos will not attempt it again. This is not a courtesy — repeatedly mailing addresses that reject you is the fastest way to lose a sending reputation.

  • Per account, visible and exportable
  • Remove an address yourself when you know it is fixed
  • Suppressed sends do not count against your monthly volume

06 API keys

Issue one key per application, per environment, or per agent. Revoking the key your staging box uses should never take production down with it, so each one stands alone.

  • Scoped to a domain, revoked individually
  • Last-used timestamp, so dead keys are findable
  • Shown once at creation and never again

The specifics.

The details you would otherwise have to open a support ticket to find out.

Send protocols
HTTPS · SMTP (587, STARTTLS)
Body formats
HTML · plain text · both
Authentication applied
SPF · DKIM · DMARC (strict)
Return path
Pharos-managed, per domain
Sender domains
unlimited, every plan
Event log retention
120 days, every plan
Max message size
50 MB including attachments
Rate limit
5 messages/second

The rate limit is a steady-state ceiling, not a monthly cap — 5 messages a second is roughly 430,000 a day, comfortably above every plan's allowance. A burst above it is queued and drained rather than rejected.

All of it, on the free plan.

3,000 emails a month, every feature on this page, no card required.

start free