Getting started / Authentication
Authentication
Every request carries an API key as a bearer token. There is nothing else to configure — no signing, no OAuth flow, no client id.
The header
Send your key in the Authorization header on every request.
https://api.pharos.email/v1 is HTTPS only, so the key is never on the wire in clear text.
A key belongs to one sending domain
Each key is issued against a single verified sending domain, and that is the domain its mail leaves from. If you send from two domains, you hold two keys.
The domain in from is the key's domain, whatever you put there.
Pharos keeps the local part and uses the key's verified domain — so
receipts@typo.com sent with a key for yourapp.com leaves as
receipts@yourapp.com. A key cannot send as a domain it was not issued for, and a
typo cannot leak mail to the wrong sender. It also means a wrong domain is corrected rather
than refused, so check the address on your first send rather than assuming a
202 means the from was right.
Creating a key
In the dashboard, open Transactional, choose your sending domain, and find the API keys section. Create API key generates one for that domain.
Copy it when it appears. The key is shown once and cannot be retrieved afterwards. If you lose it, replace it — there is no way to read an existing key back.
Each sending domain has one active key at a time. Sending from two domains means two keys, one per domain. There is no way to hold two keys for the same domain, which is worth knowing before you plan a rotation — see below.
When a key is refused
Every failure here is 401 with "type": "invalid_key". The message does
not say which of these it was, on purpose — telling an anonymous caller whether a key exists
helps nobody except somebody guessing keys.
Bearer <key> Send the header. The gateway cannot guess.
A 401 will not succeed on a retry. Fix the key rather than backing off — see
errors and limits.
Rotating a key
The same section has a Replace API key button. It issues a new key and invalidates the old one.
Replacing is a cutover, not an overlap. Because a domain has only one active
key, the old one stops working the moment the new one exists — there is no window in which
both are valid. Anything still holding the old key gets 401 until you deploy the
new one, so have the deploy ready before you click, rather than after.
Rotate when someone with access leaves, when a key has been somewhere it should not have been, or on whatever schedule your own policy sets. If you think a key has leaked, replace it first and tell us second — security@pharos.email.
Keeping a key safe
- Server-side only. A key in browser JavaScript, a mobile app, or anything else a user can open is a key anybody can read and use to send as you.
- Out of the repository. Environment variables or your secret manager. A key committed once stays in the history after you delete it, so a leak means rotate, not amend.
- Read it from one place. A domain has a single key, so every integration that sends for it shares one — which means a leak anywhere is a replacement everywhere. Keep it in one secret that each service reads, rather than pasted into several.
- Out of logs and error trackers. Request loggers capture headers by default. Check what yours does before it captures a key into a system somebody else administers.
SMTP is separate
The relay at smtp.pharosinfra.net:587 uses its own username and
password, not this key. Same pipeline and the same events either way — the credentials are just
different, so revoking one does not affect the other.
Unlike sending keys, SMTP credentials you can create yourself: they are on the sending domain's own screen in the dashboard. Setting up the SMTP relay walks through it.
curl https://api.pharos.email/v1/send \
-H "Authorization: Bearer $PHAROS_API_KEY" \
-H "Content-Type: application/json" \
-d '{...}' {
"error": {
"type": "invalid_key",
"message": "This API key is not valid.",
"docs": "/docs/authentication"
}
} # a suppressed or invalid recipient is
# still a real auth check — a 401 means
# the key, anything else means the body
curl -i https://api.pharos.email/v1/send \
-H "Authorization: Bearer $PHAROS_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'