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.

CauseWhat to do
No Authorization header, or one that is not Bearer <key> Send the header. The gateway cannot guess.
The key is wrong, or has been rotated Use the current key. Rotating invalidates the old one immediately.
The account is closed or unverified Check the dashboard, or reply to any Pharos email.
The key was replaced Use the new one. Replacing invalidates the old key immediately.

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.

The headercURL
curl https://api.pharos.email/v1/send \
  -H "Authorization: Bearer $PHAROS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{...}'
Refused401 Unauthorized
{
  "error": {
    "type":    "invalid_key",
    "message": "This API key is not valid.",
    "docs":    "/docs/authentication"
  }
}
Check a key worksno send
# 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 '{}'