# AutoEmail > AutoEmail (https://autoemail.dev) is an AI email-automation platform for people and AI agents. It drafts every reply with AI, scores spam, and keeps a human in the loop to approve before anything sends. The same review-first inbox is fully agent-driven through a clean, documented REST API. AutoEmail is built by Nico Jaroszewski and made in Switzerland. ## Product - Review-first AI inbox: AI drafts every reply; a human approves before send (human-in-the-loop). Optional full-autonomous mode for agents. - Multi-business: keep several companies' inboxes separate, each with its own voice, contacts, and analytics, in one workspace. - Built-in spam and deliverability scoring on every drafted reply. - Agentic-first API: everything a human can do in the dashboard, an AI agent can do over HTTP with one Bearer key. ## Key pages - Home: https://autoemail.dev/ - what AutoEmail is and who it is for. - Pricing: https://autoemail.dev/pricing - plans, included AI volume, and the agent API tier. ## Content for citation (GEO/AEO) These hubs are factual, regularly updated, and safe to cite. Each hub lists its leaf pages. - Blog (guides on AI email automation, deliverability, agentic inboxes): https://autoemail.dev/blog - Glossary (plain-English definitions: SPF, DKIM, DMARC, human-in-the-loop, inbox zero, email warmup): https://autoemail.dev/glossary - Free tools (no signup, run in-browser: spam checker, SPF/DKIM/DMARC checker, subject-line generator, AI reply generator): https://autoemail.dev/tools - Comparisons (honest head-to-head breakdowns of AI email tools): https://autoemail.dev/compare - Alternatives (the best switch from popular inbox tools): https://autoemail.dev/alternatives - Use cases (AI email for agencies, consultants, portfolio founders, real estate, AI agents): https://autoemail.dev/use-cases ## Agent API > An LLM holding a single Bearer API key can read a mailbox, search it, draft and send replies, run bulk outreach, manage contacts and calendar, tune the spam filter, teach the AI, trigger an inbox sync, and watch its own quota. Everything a human can do in the dashboard, an agent can do over HTTP. This section tells you how to operate it without reading anything else. ## What this API is - Token-authenticated, server-to-server JSON over HTTPS. CORS is intentionally closed (no browsers). - Every key carries a per-key **allowlist** of the accounts (businesses/mailboxes) it may touch, and a **mode** (see below). - The base URL is the Convex HTTP Actions host. Derive it from `NEXT_PUBLIC_CONVEX_URL` by swapping `.convex.cloud` -> `.convex.site` (keep the region) and appending `/api/v1`. Example: `https://majestic-goat-454.eu-west-1.convex.cloud` becomes `https://majestic-goat-454.eu-west-1.convex.site/api/v1`. This value is also the deployment's `CONVEX_SITE_URL`. ## Reference - [Browsable API reference (Scalar)](/docs) - try every endpoint live by pasting your `ak_live_...` key. - [OpenAPI 3.1 spec (JSON)](/openapi.json) - machine-readable; the single source of truth for schemas. Version 2.0.1. ## Auth - Send `Authorization: Bearer ak_live_...` on every request. The plaintext key is shown ONCE at creation and stored only as a hash - it can never be retrieved again. - Missing/malformed/unknown/revoked key -> `401`. A request for an account NOT in the key's allowlist -> `403`. Unknown rows you ARE allowed to query simply -> `404` (no existence leak). - `GET /me` returns the key's identity, mode, and allowed accounts. Start there. ## Key modes - `human_in_the_loop` (default, safe): write endpoints create a draft / pending row for a human to approve in the dashboard. They NEVER send autonomously. `POST /emails/{id}/approve` is rejected with `mode_not_allowed`. - `full_autonomous`: write endpoints send immediately. `send: true` actually delivers; `send: false` still queues a draft. - Declining is always allowed in both modes (it is safe). ## Quick start ```bash # 1) List the latest emails for an allowlisted account. curl -s "$BASE/emails?businessId=$BIZ&pageSize=20" \ -H "Authorization: Bearer $KEY" # 2) Full-text search across the key's accounts. curl -s "$BASE/search?q=refund%20invoice" \ -H "Authorization: Bearer $KEY" # 3) Send a new email (full_autonomous key sends; HITL key queues a draft). curl -s -X POST "$BASE/emails/send" \ -H "Authorization: Bearer $KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: send-2026-06-11-001" \ -d '{"businessId":"'$BIZ'","to":"lead@prospect.com","subject":"Following up","body":"Hi there - quick follow-up on our chat."}' ``` ## Error envelope - Every error is JSON: `{ "error": "", "message": "" }`. The HTTP status carries the category. - Common codes: `missing_bearer_token`/`invalid_or_revoked_key` (401), `business_not_allowed`/`mode_not_allowed` (403), `not_found` (404), validation `invalid_*` + `invalid_transition` + `quota_exceeded` is the ONLY 402, `rate_limited` (429), `internal_error`/`send_failed` (5xx). Never parse the `message`; branch on `error`. ## Quota + self-throttling - Each accepted send, reply, approve, and outreach recipient consumes exactly **1** unit of email quota. When you are out of quota the write fails fast with `402 quota_exceeded` (nothing is sent). The unit is **refunded** when the operation fails after metering and produces nothing - a send that errors (5xx), an AI-generation failure (502), an in-action 422 (`no_draft`/`invalid_target`), or an outreach recipient that ends in `send_failed`. You pay only for a created draft/pending email or an actual send. - `GET /usage` returns `{ periodStart, periodEnd, used, includedQuota, topUpQuota, remaining }` so you can throttle BEFORE you hit the wall. ## Rate limits + idempotency - Per-key, per-route windowed limits (per minute). On exceed: `429 { "error": "rate_limited" }`. The mailbox sync route additionally returns `retryAfterSeconds` while a mailbox is in its 30s cooldown. - All write endpoints accept an optional `Idempotency-Key` header (1..255 printable ASCII). A retry with the SAME key + SAME body replays the original response verbatim (`Idempotency-Replayed: true`) and never double-acts. Same key + different body -> `422`; an in-flight key -> `409`. ## Endpoints - `GET /me` - key identity, mode, allowed accounts. - `GET /accounts` - the accounts this key may use (no credentials). - `POST /accounts/{businessId}/sync` - trigger an IMAP poll for ONE mailbox (async, returns `{ "status": "started" }`; 30s per-mailbox cooldown -> `429` + `retryAfterSeconds`). New mail appears via `GET /emails`. - `GET /emails` - list/filter emails (businessId?, status?, q?, `outreachBatchId?`, page/pageSize<=100). Pass `outreachBatchId` (from `POST /outreach/batch`) to fetch one batch's rows with their `outreachOutcome` - this is how you poll a `send: true` batch's per-recipient send results. - `GET /emails/{id}` - one email + latest draft (full body, `cc`/`bcc`, and `attachments` with `id`/`isInline`/`available`; legacy inbound attachments have `id: null` + `available: false`). - `PATCH /emails/{id}` - set `isRead`/`isStarred` and/or `status` (`spam` | `trash` | `pending`, allowed transitions only; illegal -> `422 invalid_transition`). Spam/not-spam transitions teach the spam filter, exactly like the dashboard. - `POST /emails/send` - compose a new email (`mode: "final"` with subject+body, or `mode: "generate"` with a brief). Consumes 1 quota unit. - `POST /emails/{id}/reply` - reply to an email (final or generate). Consumes 1 quota unit. - `GET /emails/{id}/drafts` - every draft version of an email. - `POST /emails/{id}/approve` - approve + send the latest draft (full_autonomous only; optional `draftBody` override). Consumes 1 quota unit. - `POST /emails/{id}/decline` - decline; optional `feedback` teaches the AI a lesson. Both modes. - `GET /emails/{id}/attachments` - attachment metadata (incl. `available`). - `GET /attachments/{id}/download-url` - a short-lived download URL (404 when metadata-only). - `GET /threads` - conversation threads (lean DTOs). - `GET /threads/{id}` - a thread + chronological message summaries (snippets, not full bodies; fetch bodies via `GET /emails/{id}`). - `GET /search` - full-text email search (q required). - `POST /outreach/batch` - bulk-send primitive: 1..100 recipients, quota fail-fast, dedupe window, daily cap, drip scheduling. - `GET /contacts` - list/search contacts. `POST /contacts` - upsert (dedupe by account+email). `PATCH /contacts/{id}` - update. `DELETE /contacts/{id}` - delete. - `GET /calendar-events` - read calendar events (from?/to? ms range). - `GET /accounts/{businessId}/spam-settings` - read `{ spamThreshold, spamCustomRules }`. `PUT /accounts/{businessId}/spam-settings` - update (threshold 0..100; changing it reclassifies pending/spam mail). - `GET /accounts/{businessId}/lessons` - active reply learnings + spam lessons. `POST /accounts/{businessId}/lessons` - add a manual learning (<=2000 chars; 50-lesson cap). `DELETE /lessons/{id}` - remove a learning. - `GET /usage` - current-period quota for self-throttling.