API
Sign in via AuthLock at /login; send the session token as the
e2sid cookie or Authorization: Bearer. Bodies are end-to-end encrypted on the device.
Sign-in
POST /api/authlock/session — Exchange an AuthLock widget handoff code for a session.
Auth: none (same-origin) · Body: { code, next? } · Response: { token, csrf, redirectTo }
The email must be verified at AuthLock. The token is also set as the e2sid cookie; native apps send it as Bearer.
DELETE /api/authlock/session — Sign out of this service.
Auth: session · Response: { ok }
POST /api/authlock/webhook — AuthLock events (blocked/deleted users are signed out everywhere).
Auth: authlock-signature · Response: { ok }
Account
GET /api/me — The signed-in user, public key and change cursor.
Auth: session · Response: { user, seq, unlockedOnServer, sessions }
POST /api/identity — Upload the identity key made on the device (passphrase-wrapped).
Auth: session · Body: { publicKey, wrappedKey } · Response: { ok, fingerprint }
Only when the account has no key yet, or within 10 minutes of signing in with { replace: true }.
Mailboxes
GET /api/saas/mailboxes — WorkflowEmail mailboxes this user can reach.
Auth: session · Response: { mailboxes: [{ address, canSend, lastSync, error }] }
POST /api/saas/mailboxes/refresh — Ask WorkflowEmail again (after being added to a domain).
Auth: session · Response: { ok, reason?, mailboxes }
GET /api/sync?since=<seq> — Changes since a cursor — messages, threads, labels, contacts, accounts.
Auth: session · Response: { changes, deleted, seq, more }
POST /api/ops — Idempotent batch of operations (flags, labels, send, draft, contacts, settings).
Auth: session · Body: { ops: [{ id, kind, payload }] } · Response: { results, seq }
send/draft carry an envelope already encrypted on the device.
POST /api/fetch — Pull new mail from WorkflowEmail now and flush the outbox.
Auth: session · Response: { results, sent }
GET /api/search?q= — Search headers (bodies are encrypted; search them on the device).
Auth: session · Response: { items }
Keys
GET /api/keys?address=a@x,b@y — Find public keys for recipients and file them as contacts.
Auth: session · Response: { found: [{ address, fingerprint, source }] }
GET /.well-known/e2email/keys?address= — Public key directory for users of this service.
Auth: none (rate limited) · Response: { address, publicKey, fingerprint }
Point another e2email server here with E2E_KEY_DIRECTORY to encrypt to our users.
Service
GET /healthz — Liveness.
Auth: none · Response: { ok }