One platform, three doors: a transactional send API for integrators, the mailbox web API for humans, and a native MCP server for AI agents. Every message leaves ML-DSA-65-signed; every mailbox is ML-KEM-768-sealed.
curl -X POST https://iset.email/v1/emails \
-H "Authorization: Bearer isk_…" -H "content-type: application/json" \
-d '{"from":"hi@yourdomain.com","to":"user@example.com","subject":"Signed","html":"<p>sealed & signed</p>"}'
Mint a domain key in the console (Connect a domain → keys). The from address must live on the key's domain. Accepted mail returns an id and emits signed lifecycle envelopes.
curl -X POST https://iset.email/v1/mailboxes \
-H "Authorization: Bearer isk_…" -H "content-type: application/json" \
-d '{"address":"alice@yourdomain.com","kind":"agent"}'
Native Model Context Protocol — list, search, read, ask-inbox, draft, send. Generate a scoped key in Settings → Connect AI agents (read-only or full), or connect with zero configuration via OAuth discovery.
{
"mcpServers": { "iset-email": {
"command": "npx", "args": ["-y", "mcp-remote", "https://iset.email/mcp",
"--header", "Authorization: Bearer YOUR_KEY"] } }
}
Endpoint: https://iset.email/mcp · JSON-RPC 2.0 · Streamable HTTP · stateless
Signed in: GET https://iset.email/v2/export streams every message as NDJSON. End-to-end-sealed mail exports as ciphertext — readable only with your key. That's the point.
| Concern | Behavior |
|---|---|
| Errors | { "error": { "code": "…", "message": "…" } } with correct HTTP status (401 · 403 · 404 · 409 · 422 · 429 · 5xx) |
| Rate limits | Per-tier daily sends (100 / 300 / 500; Verified ID +50%) → 429 + Retry-After |
| Auth scopes | isk_ one domain · mcp_ read|full, revocable · oat_ OAuth, 30-day, refresh-rotated, revocable |
| Signed mail | X-Sovereign-Sig (ML-DSA-65, FIPS 204) + ISP envelope codes on every state change |
| E2E line | Sealed mail is never decrypted for agents — a statement is returned instead of plaintext |
/openapi.json
/mcp-demo
docs/api-architecture.md (repo)