{"name":"e2email","baseUrl":"https://o8ln2.viberunner.org","human":"/docs/api","llm":"/docs/llm/api.md","endpoints":[{"group":"Sign-in","method":"POST","path":"/api/authlock/session","auth":"none (same-origin)","summary":"Exchange an AuthLock widget handoff code for a session.","body":"{ code, next? }","response":"{ token, csrf, redirectTo }","notes":"The email must be verified at AuthLock. The token is also set as the e2sid cookie; native apps send it as Bearer."},{"group":"Sign-in","method":"DELETE","path":"/api/authlock/session","auth":"session","summary":"Sign out of this service.","response":"{ ok }"},{"group":"Sign-in","method":"POST","path":"/api/authlock/webhook","auth":"authlock-signature","summary":"AuthLock events (blocked/deleted users are signed out everywhere).","response":"{ ok }"},{"group":"Account","method":"GET","path":"/api/me","auth":"session","summary":"The signed-in user, public key and change cursor.","response":"{ user, seq, unlockedOnServer, sessions }"},{"group":"Account","method":"POST","path":"/api/identity","auth":"session","summary":"Upload the identity key made on the device (passphrase-wrapped).","body":"{ publicKey, wrappedKey, replace?, stolen? }","response":"{ ok, fingerprint, keyChange?, stripped? }","notes":"Only when the account has no key yet, or within 10 minutes of signing in with { replace: true }; at most 3 replacements a day (429). 409 for a key that is (or was) another account's. A replacement is recorded as a pending key change for the other members of your shared mailboxes to approve, and your old fingerprint is removed from your own messages and from the copies of the mailboxes you are a member of — never from anyone else's private mail. Until approved, the new key reads only your own copies."},{"group":"Mailboxes","method":"GET","path":"/api/saas/mailboxes","auth":"session","summary":"WorkflowEmail mailboxes this user can reach.","response":"{ mailboxes: [{ id, accountId, address, canSend, lastSync, error }] }"},{"group":"Mailboxes","method":"GET","path":"/api/saas/mailboxes/:id/members","auth":"session (member)","summary":"Members of one of your mailboxes (:id = your account id or mailbox id) and their keys.","response":"{ mailbox, members: [{ userId, address, name, fingerprint, publicKey, trusted, rejected, lastKeyChange, recovery? }] }"},{"group":"Mailboxes","method":"GET","path":"/api/saas/seal-keys?account=","auth":"session","summary":"Extra keys to seal what you store for an account to: the other members' trusted keys (first key or approved; not rejected for this mailbox), your recovery key.","response":"{ keys: [{ address, publicKey, fingerprint }] }"},{"group":"Key changes","method":"GET","path":"/api/saas/key-changes","auth":"session","summary":"Your latest key change, and colleagues' new keys waiting for you.","response":"{ mine, toApprove, approvedByMe, recoveryKey, notices }"},{"group":"Key changes","method":"POST","path":"/api/saas/notices/:id/seen","auth":"session","summary":"Dismiss a security notice (e.g. \"A recovery key was added to your account\").","response":"{ ok }"},{"group":"Key changes","method":"POST","path":"/api/saas/key-changes/:id/approve","auth":"session, signed in ≤ 10 min ago, member of a shared mailbox","summary":"Approve a colleague's new key after checking its fingerprint with them by phone or in person.","body":"{ fingerprint }","response":"{ ok, keyChange }","notes":"409 unless the fingerprint is exactly the pending one; 403 for a stale session or a non-member."},{"group":"Key changes","method":"POST","path":"/api/saas/key-changes/:id/reject","auth":"session, signed in ≤ 10 min ago, member of a shared mailbox","summary":"Reject a colleague's new key for the shared mailboxes you have in common with them (your copies and that address's directory entry); their personal address is unaffected.","response":"{ ok }"},{"group":"Key changes","method":"POST","path":"/api/saas/key-changes/:id/complete","auth":"session (the approving member)","summary":"Report the re-key job finished: no further re-key / re-seal ops under this change.","response":"{ ok }"},{"group":"Key changes","method":"GET","path":"/api/saas/rekey/work?scope=change|own|recovery&change=&phase=theirs|mine&after=&limit=","auth":"session","summary":"A page (≤ 200) of messages to re-key: key slots only, plus the target keys and stale fingerprints per account.","response":"{ items: [{ id, account_id, keys, mine, mineKeys?, resealed, refetchable }], accounts: { [accountId]: { target, drop } }, next, total?, since, subject, completed? }"},{"group":"Key changes","method":"POST","path":"/api/saas/rekey","auth":"session","summary":"Apply re-key ops, all or nothing (≤ 16 MB, ≤ 200 ops, at most 4 such requests at a time service-wide: 429).","body":"{ ops: [{ kind: \"message.rekey\", id, keys } | { kind: \"message.reseal\", id, from }] }","response":"{ ok, applied }","notes":"message.rekey changes only envelope.keys: added slots must be current members' (approved) keys, removed slots must belong to no current member, existing slots may not be rewritten. On a colleague's message you must share its mailbox (403) and have approved their current key (409), from a fresh sign-in or the approving session (for 24 h after approving, until the job is reported complete; 409 after). message.reseal (a colleague's copy that has no slot for their current key, once per copy) carries no envelope: the server copies your own copy `from` of the same message in the same shared mailbox — which must already have a slot for their new key — with its slots filtered to the current trusted members, and marks it \"restored from your copy\"."},{"group":"Key changes","method":"POST","path":"/api/saas/rekey/refetch","auth":"session (owner, or the approving member)","summary":"Fetch mail that travelled in the clear again from WorkflowEmail and seal it to the owner's current key (≤ 20 ids; at most 2 such requests at a time service-wide: 429).","body":"{ ids }","response":"{ results: [{ id, ok, error? }] }"},{"group":"Key changes","method":"GET","path":"/api/saas/recovery-key","auth":"session","summary":"Your recovery key: public half and the phrase-wrapped private half.","response":"{ exists, fingerprint?, publicKey?, wrappedKey? }"},{"group":"Key changes","method":"PUT","path":"/api/saas/recovery-key","auth":"session, signed in ≤ 10 min ago","summary":"Create or replace your recovery key (409 if it is another account's key). You are told about it on your next visit.","body":"{ publicKey, wrappedKey }","response":"{ ok, fingerprint }"},{"group":"Key changes","method":"DELETE","path":"/api/saas/recovery-key","auth":"session, signed in ≤ 10 min ago","summary":"Remove your recovery key (and its slots).","response":"{ ok }"},{"group":"Mailboxes","method":"POST","path":"/api/saas/mailboxes/refresh","auth":"session","summary":"Ask WorkflowEmail again (after being added to a domain).","response":"{ ok, reason?, mailboxes }"},{"group":"Mail","method":"GET","path":"/api/sync?since=<seq>","auth":"session","summary":"Changes since a cursor — messages, threads, labels, contacts, accounts.","response":"{ changes, deleted, seq, more }"},{"group":"Mail","method":"POST","path":"/api/ops","auth":"session","summary":"Idempotent batch of operations (flags, labels, send, draft, contacts, settings).","body":"{ ops: [{ id, kind, payload }] }","response":"{ results, seq }","notes":"send/draft carry an envelope already encrypted on the device."},{"group":"Mail","method":"POST","path":"/api/fetch","auth":"session","summary":"Pull new mail from WorkflowEmail now and flush the outbox.","response":"{ results, sent }"},{"group":"Mail","method":"GET","path":"/api/search?q=","auth":"session","summary":"Search headers (bodies are encrypted; search them on the device).","response":"{ items }"},{"group":"Keys","method":"GET","path":"/api/keys?address=a@x,b@y","auth":"session","summary":"Find public keys for recipients and file them as contacts.","response":"{ found: [{ address, fingerprint, source }] }"},{"group":"Keys","method":"GET","path":"/.well-known/e2email/keys?address=","auth":"none (rate limited)","summary":"Public key directory for users of this service.","response":"{ address, publicKey, fingerprint, keys: [{ publicKey, fingerprint }] }","notes":"Point another e2email server here with E2E_KEY_DIRECTORY to encrypt to our users. An address several people share lists every key in keys[]; encrypt to all of them."},{"group":"Service","method":"GET","path":"/healthz","auth":"none","summary":"Liveness.","response":"{ ok }"}]}