Documentation
Getting started

Quickstart — send your first email in five minutes

5 min read

This is the five-minute path from nothing to a delivered email and a structured reply event. Every call here is plain HTTPS against https://api.mails.ai with an Authorization: Bearerheader — no SDK to install, no glue code. The official SDKs and MCP server ship at Phase 1 launch and wrap exactly this REST surface; the API below is the interface today and the foundation underneath the SDKs later.

1. Get an API key

Sign in at app.mails.ai (magic link, Google, or passkey) and mint a key under API keys. During the closed beta, request access from support@mails.ai with a one-line description of what you are building. Keys look like mk_live_… (or mk_test_…for the test mode) and are shown exactly once at creation — store it in an environment variable:

export MAILS_API_KEY="mk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Every request authenticates with that key in the standard bearer header. A request with no key gets a structured 401 telling you exactly what is missing — see Authentication for scopes, key modes, and rotation.

2. Create an agent

An agentis a named sending identity inside your workspace. It owns an email address, a reputation score, and optional send limits. Create one with a single field — the name becomes the local part of <name>@<workspace>.mails.ai:

curl https://api.mails.ai/v1/agents \
  -H "Authorization: Bearer $MAILS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "sarah" }'

Returns the agent, including the address it sends from:

{
  "id": "agt_01J9X2K7Q8WERTY...",
  "name": "sarah",
  "email": "sarah@acme.mails.ai",
  "domain": "acme.mails.ai",
  "workspace_id": "wsk_01J9X2...",
  "status": "active",
  "created_at": "2026-06-19T17:24:08.512Z"
}

3. Send your first email

POST /v1/messages sends one message. Address the agent by name (or by its agt_ id), give it a recipient, a subject, and a text or HTML body:

curl https://api.mails.ai/v1/messages \
  -H "Authorization: Bearer $MAILS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent": "sarah",
    "to": "user@example.com",
    "subject": "Welcome aboard",
    "body_text": "Thanks for signing up — reply any time and I will read it."
  }'

The same call in TypeScript, using nothing but fetch:

const res = await fetch("https://api.mails.ai/v1/messages", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.MAILS_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    agent: "sarah",
    to: "user@example.com",
    subject: "Welcome aboard",
    body_text: "Thanks for signing up — reply any time and I will read it.",
  }),
});

const message = await res.json();
console.log(message.id, message.status); // msg_01J9…  sent

A 201 returns the sent message. routing_pool is the pool the server classified the send into, and cost_usd is what the send cost on your plan:

{
  "id": "msg_01J9X2K7Q8ABCDEF...",
  "agent_id": "agt_01J9X2K7Q8WERTY...",
  "thread_id": "thrd_01J9X2K7Q8...",
  "to": ["user@example.com"],
  "subject": "Welcome aboard",
  "routing_pool": "clean",
  "classifier_score": 0.03,
  "status": "sent",
  "cost_usd": 0.0001,
  "created_at": "2026-06-19T17:25:11.004Z"
}
Got 403 workspace_not_approved? Sending is gated on workspace approval to keep the shared pool clean. Everything else — agents, keys, reads — works before approval. Request it from support@mails.ai during the beta.

4. Receive the reply

When user@example.com replies, the inbound is parsed into a structured event — with injection_score and sender_reputation on every reply, plus intent and entities if you enable classification on the agent. There are two ways to consume it.

Poll the events feed— simplest to start with:

curl "https://api.mails.ai/v1/events?event_type=message.received" \
  -H "Authorization: Bearer $MAILS_API_KEY"

Or register a webhook so events are pushed to your endpoint as they arrive (HMAC-signed, retried with backoff):

curl https://api.mails.ai/v1/webhooks \
  -H "Authorization: Bearer $MAILS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/inbound",
    "event_types": ["message.received"]
  }'

For the live tail — a long-lived stream of every event as it happens — see the events & streaming guide. For verifying webhook signatures, see webhooks.

What you just built

A working agent address that sends real email and turns every reply into a structured, scored event your code can branch on. From here:

  • Authentication— key scopes (send / read / manage), test vs live mode, rotation.
  • Concepts— how workspaces, agents, messages, events, and threads relate.
  • API reference— every endpoint, request and response shape, with the exact fields.
  • Errors— the error envelope and every code you can get back.

Common questions

Do I need to install an SDK?

No. The mails.ai API is plain HTTPS + JSON — everything in this quickstart is curl and fetch. The TypeScript (@mailsai/sdk), Python (mailsai), and MCP server (@mailsai/mcp-server) packages are thin wrappers over this same REST surface and publish at Phase 1 launch (Q3 2026). Until then, and forever after, the REST API is the canonical interface.

Why did my send return 403 workspace_not_approved?

Sending is gated on workspace approval. A newly created workspace can authenticate, create agents, read, and manage immediately, but cannot send until approved — this is how mails.ai keeps the shared sending pool clean. During closed beta, request approval from support@mails.ai with a one-line description of what you are sending. Read and manage endpoints work before approval.

Where does the email actually send from?

From your agent's address, <agent>@<workspace-slug>.mails.ai — e.g. sarah@acme.mails.ai. Each agent is a named sending identity inside your workspace with its own address, reputation, and optional per-agent send limits. Custom sending domains are a Phase 2 capability; today every agent sends from your workspace subdomain.