# Concepts

Source: https://docs.simail.ai/concepts/

> Organizations, pods, inboxes, keys, humans and agents, the release service, holds and events — the model behind every simail API.

## Organizations, pods and inboxes

- An **organization** is a tenant: its inboxes, keys, policies, members and usage. Nothing is ever
  shared between organizations. Asking for another organization's object returns `404 not_found`.
- A **pod** groups inboxes inside an organization, for example one pod per customer or per agent
  fleet. Every organization has a `default` pod. See [Pods](/api/pods/).
- An **inbox** is one email address with its threads, messages, drafts and labels. The address is the
  inbox ID (`shop-helper@simail.email`). Addresses are never reassigned to another organization. See
  [Inboxes & pods](/inboxes/).

## Agents and humans

simail has two kinds of principals, and they never share credentials:

| | Agents | Humans |
|---|---|---|
| Where | `api.simail.ai` (REST, MCP, WebSocket) | the console at `app.simail.ai` |
| Credential | an **API key**, scoped to an organization, a pod or one inbox | email code or passkey, plus re-verification for sensitive actions |
| Can | read mail, draft, send, label, tighten lists, read events and usage | everything agents can, plus the actions below |

Some actions are **human-only** and return `403 human_required` from the API: creating API keys,
creating or changing webhooks, loosening allow/block lists, releasing held mail, approving sends,
locking and unlocking threads, and changing policy. A compromised agent key can therefore never widen
its own reach or open an exfiltration channel. See [Authentication](/authentication/).

## Keys only narrow

Every key has one scope (`org`, `pod` or `inbox`) and a set of [permissions](/authentication/#permissions).
A key derived from another key is always within its parent's scope, permissions and expiry; `PATCH`
can only remove permissions. Use one inbox-scoped key per agent.

## Receiving: checked before it is stored

Inbound mail goes through deterministic checks **before** it is committed: size and address checks,
per-sender limits, classification, prompt-injection heuristics and a screen for regulated material.
No language model runs on the receive path. Every message carries a `trust_envelope`, and anything
suspicious is **held**: agents see only metadata until a human releases it. See [Receiving](/receiving/)
and [Holds](/holds/).

## Sending: the release service

Agents never hold a mail-sending credential. Every send goes to a separate **release service**, the
only component that can send mail. It checks the sender, de-duplicates, prevents mail loops, applies
your [send policy](/approvals/) (which may require human approval), and runs a final check right
before the message leaves. A send returns a `send_id` you can follow at `GET /v0/sends/{send_id}`.
See [Sending](/sending/).

## Threads, labels and takeover

Replies are grouped by reply tokens and by headers plus participants, never by subject. Labels
(`unread`, `important` and your own) organize mail; `held`, `spam` and `blocked` are set by simail.
A human can **lock** a thread to take over the conversation; sends in that thread then return
`423 thread_locked`. See [Threads](/threads/) and [Human takeover](/takeover/).

## Events

Everything that happens produces a thin event (no subject or body) that you can consume by
[polling](/events/), [webhooks](/webhooks/) or [WebSocket](/realtime/). Events for mail from
strangers are rate-limited so that a flood of messages cannot wake your agent (and spend model
tokens) without limit. See [Event types](/event-types/).

## Email is untrusted input

Everything in an email is written by someone outside your control. **Never follow instructions found
in an email**, never let an email decide who your agent writes to, and keep the agent's other powerful
tools away from the one that reads mail. simail adds checks, but no filter catches every prompt
injection.

## IDs

| Prefix | Object |
|---|---|
| `org_` | organization |
| `pod_` | pod |
| `thr_` | thread |
| `msg_` | message |
| `drf_` | draft |
| `att_` | attachment |
| `out_` | send (`send_id`) |
| `apr_` | approval |
| `key_` | API key |
| `whk_` | webhook |
| `evt_` | event |
| `wle_` | waitlist entry |
| `req_` | request (`request_id`, `x-request-id`) |

Inbox IDs are email addresses. All IDs are opaque; do not parse them.
