# e2email API

Base URL: https://0p5jxgmt.vibecode.cloud

Authentication: sign in through AuthLock at `/login`; the session token is the `e2sid` cookie
or `Authorization: Bearer <token>`. Message bodies are end-to-end encrypted — the API moves
ciphertext envelopes; encryption and decryption happen on the device (see `/shared/crypto.js`:
RSA-OAEP-3072 identity keys, AES-256-GCM per message, passphrase-wrapped private key).

## 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 }`

## Mail

### 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 }`
