# Managed email API

> Connect a backend, Claude, or another agent to tenant-safe domains, mailboxes, threads, and sends.

## One key, one workspace
Send the workspace API key in x-api-key on every /v1/email/* request. The key resolves the workspace on Beam's server. There is no tenant id in the request body and no way to ask for another workspace.
Server-side onlyNever put a workspace key in browser JavaScript, a public agent prompt, a client-side Claude artifact, source control, logs, or screenshots. Store it in the calling system's secret manager.

## Available operations

| Method | Path | Purpose | 
| GET | /v1/email/plan | Read plan, usage, cap, and the public catalog. | 
| GET / POST | /v1/email/domains | List or provision a workspace-owned domain. | 
| POST | /v1/email/domains/:id/verify | Request verification and perform provider read-back. | 
| GET / POST | /v1/email/mailboxes | List or create identities on an owned domain. | 
| GET | /v1/email/threads | List email threads for the workspace. | 
| GET | /v1/email/threads/:id | Read one owned thread and its timeline. | 
| POST | /v1/email/messages | Start a one-to-one email thread. | 
| POST | /v1/email/threads/:id/messages | Reply on an owned thread. | 
| POST | /v1/email/threads/:id/takeover | Pause or deliberately resume the assistant. | 

## Send example
curlJavaScriptCopy
```
curl -X POST https://beam.aisync.link/v1/email/messages \
  -H "x-api-key: $BEAM_WORKSPACE_KEY" \
  -H "content-type: application/json" \
  -d '{"domain_id":"12","mailbox_id":"18","to":"lead@example.com","subject":"Following up","text":"Hi Maya — here is the information you asked for.","request_key":"crm-contact-847:follow-up-1"}'
```

```
const response = await fetch("https://beam.aisync.link/v1/email/messages", {
  method: "POST",
  headers: { "x-api-key": process.env.BEAM_WORKSPACE_KEY, "content-type": "application/json" },
  body: JSON.stringify({ domain_id: "12", mailbox_id: "18", to: "lead@example.com", subject: "Following up", text: "Hi Maya — here is the information you asked for.", request_key: "crm-contact-847:follow-up-1" }),
});
```

## Idempotency and delivery truth
request_key is required for sends. Reuse the same key for a retry of the same business action; Beam returns the original record and does not consume another allowance unit. A 202 response means queued, not delivered. Use the thread timeline and signed events for final state. Never automatically retry delivery_unknown.

## Claude and agent use
Give the agent the LLM documentation corpus and OpenAPI contract, but inject the workspace key only into a protected server tool. Require approval for domain changes and live sends. Human takeover must call the takeover endpoint before the agent stops working the thread.
