$ docs
Send your first email in 60 seconds.
Two paths in, no SDK to install. Everything here is plain HTTP or plain SMTP, and every example is runnable as written.
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>"
}' # 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 // no SDK required
await fetch("https://api.pharos.email/v1/send", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PHAROS_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({ from, to, subject, html })
}); # no SDK required
import os, requests
requests.post(
"https://api.pharos.email/v1/send",
headers={"Authorization": f"Bearer {os.environ['PHAROS_API_KEY']}"},
json={
"from": "receipts@yourapp.com",
"to": "customer@example.com",
"subject": "Your receipt from Acme",
"html": "<p>Thanks for your order.</p>",
},
) // no SDK required
$ch = curl_init("https://api.pharos.email/v1/send");
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("PHAROS_API_KEY"),
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode($message),
CURLOPT_RETURNTRANSFER => true,
]);
curl_exec($ch); The three things you need
- 1
A verified sending domain
Add the domain you send from and publish the DNS records Pharos gives you. Until it verifies, that domain cannot send — a message is rejected rather than delivered unsigned. Most of the ten minutes is DNS propagation.
- 2
An API key
Create one in the dashboard on the sending domain itself. A domain has one active key, it is shown once, and mail sent with it leaves from that domain whatever you put in
from— see authentication. - 3
One HTTP call
POST https://api.pharos.email/v1/sendwith four fields. A202means queued, signed and aligned — not yet delivered. What happened next is in events.
Check it works
This needs no key and touches nothing. If it answers, the API is up — which is also what status.pharos.email reports.
curl https://api.pharos.email/v1/health
{"status":"ok"} What you should know before you build on it
This is how to send through Pharos; for what a receiving server does with that message and why, see how email authentication works.
- Base URL
https://api.pharos.email/v1— HTTPS only.- Errors
-
Real HTTP status codes, never a failure hidden inside a
200. One shape:{ error: { type, message, field, docs } }. Branch ontype, logmessage. - Retries
-
4xxwill fail again — fix the request.429,500and502are worth retrying. Send anIdempotency-Keyand a retry cannot become a duplicate. - Rate limit
- 100 requests per minute. Above it,
429withRetry-After. - Recipients
- Each one counts once against your monthly volume. Suppressed recipients do not count at all.
- SMTP
-
Same pipeline, same events. Point your existing mailer at
smtp.pharosinfra.net:587with STARTTLS and change nothing else — how to set it up.
Reference
- Send a message Queue one transactional message. The endpoint most integrations ever call. POST /v1/send
- Retrieve email events What happened to your mail: delivery, failure, opens, clicks and complaints. GET /v1/events
Two endpoints, both live and documented. More are coming — sender domains, suppressions and webhooks among them — and they are not listed until they answer. Tell us which you need next and it moves up the list.