Inboxes
An Extrovert inbox is a persistent email account with authenticated sending and IMAP-backed receiving. It belongs to one agent in one project. It is not a forwarding alias or catch-all.
Identity and addressing
Section titled “Identity and addressing”Every inbox has:
- an opaque
idsuch aspmbx_..., which is the stable API path key; - an email
address, accepted as a project-local path alias; - fixed
org_id,project_id, andagent_idownership; - a lifecycle
status; - an effective rolling 24-hour recipient limit;
- a read-only
direct_smtp_enabledstatus for agent clients; - optional display name, webhook URL, and metadata.
Use the opaque id for durable references. Do not parse meaning from it.
Omit username and domain to use the shared domain for the account’s plan:
| Account | Address domain |
|---|---|
| Paid account without a custom domain | extrovertmail.com |
| Free account, when free signup is enabled | free.extrovertmail.com |
| Account with a verified custom domain | The selected customer domain |
Check current free-signup availability with agent_context or GET /v1/signup-status. An existing
@free.extrovertmail.com address remains valid after
an upgrade, but newly created paid inboxes use extrovertmail.com unless a verified custom domain is
selected.
Shared-domain names
Section titled “Shared-domain names”On both platform shared domains, Extrovert normalizes the local part to lowercase, removes spaces and
unsupported characters, and then requires at least five characters. Omit username to receive a
generated agent-... name.
The following normalized names are reserved on both domains:
postmaster, admin, webadmin, legal, fraudmark, fraudmarc, keith,
melissa, richard, sydney, syd, john, and johnny.
These restrictions do not apply to customer-owned domains.
const generated = await extrovert.inboxes.create();const support = await extrovert.inboxes.create({ username: "support" });const billing = await extrovert.inboxes.create({ username: "billing", domain: "mail.acme.com", client_id: "billing-primary",});Lifecycle
Section titled “Lifecycle”-
Create. Extrovert creates the receiving account, registers the authenticated sender, seals the connection credential, and returns the inbox. POST /v1/inboxes
-
Inspect. Fetch the inbox before sending. The single-inbox response includes
effective_review_policy; list responses do not. -
Send and receive. Outbound API, SDK, and MCP requests follow review, suppression, contact-list, and daily recipient controls. Incoming mail is available through messages, threads, webhooks, and
wait_for_email. -
Manage. Update the display name, webhook, metadata, or effective daily limit when the key has the required permission.
-
Delete. Deletion removes the receiving account, sender registration, and stored messages. It cannot be undone. DELETE /v1/inboxes/{inbox_id}
Review policy applies to every outbound request
Section titled “Review policy applies to every outbound request”An inbox resolves its policy from the inbox override, then the account default, then the
require_review floor.
| Policy | Behavior |
|---|---|
require_review | Every send, reply, and forward needs an intent and normally waits for human review |
allow_direct | A bare outbound request may send immediately; an explicit review request still queues |
auto_send_graduated | A message in a graduated category can send automatically only when every deterministic gate passes |
An agent can read effective_review_policy but cannot widen it. Under require_review, omitting
intent.summary returns 422 intent_required; nothing is sent or queued.
Queued mail has not been delivered. Keep the returned rr_... id and wait for a terminal review event
or poll the review until closed is true.
Daily send accounting
Section titled “Daily send accounting”daily_send_limit is a rolling 24-hour recipient cap. A message sent to three recipients consumes
three units. A queued review consumes no capacity until delivery. A rejected request consumes none.
Changing the effective limit requires mailbox:quota plus read access and accepts values from 1 to
10,000. Enrollment keys can set the inherited limit for the agents they create; 0 in the console
means use the organization default.
Over-limit responses include 429 and Retry-After. See
Rate limits and quotas for the other limits that can apply.
Metadata
Section titled “Metadata”Metadata stores small application values on the inbox:
const inbox = await extrovert.inboxes.create({ metadata: { team: "support", tier: 2, monitored: true },});
await extrovert.inboxes.update(inbox.id, { metadata: { tier: 3, monitored: null },});Values may be strings, numbers, or booleans. Updates are shallow merges. A key set to null is
removed, and top-level null clears the object. Nested objects and arrays are rejected. Metadata is
limited to the same project as the inbox.
Receiving
Section titled “Receiving”| Method | Use it when |
|---|---|
| Messages and threads | You need bounded lists, search, read state, folders, or conversation history |
| Webhooks | A service needs signed push delivery |
wait_for_email | A task needs the next matching message, OTP, or verification link in the current turn |
The console’s Mail section exposes inboxes and conversations together. Its compose and reply actions use the same API and review rules as an agent request.
Portable email credentials
Section titled “Portable email credentials”Exporting IMAP and SMTP configuration requires mailbox:credentials and an eligible paid plan. The
normal API, SDK, and MCP path does not require the connection password. A password grants IMAP access,
but it does not by itself authorize raw SMTP submission.
Enabled SMTP follows the same review and recipient policies as API, SDK, and MCP sends. SMTP acceptance means custody, not delivery: required review waits in the review thread for approval, edits or rejection. Final dispatch applies suppression, contact-list checks, unsubscribe policy and billing. Keep the same Message-ID for an uncertain retry; changed content needs a new Message-ID. SMTP supports plain text, HTML and ordinary attachments within the outbound message limits. Unsupported formats are refused before acceptance.
The term mailbox appears in stable permission strings, fields such as max_mailboxes, and IMAP protocol
documentation. Product instructions and interface labels use inbox.
Deletion and lifetime limits
Section titled “Deletion and lifetime limits”Deleting an inbox does not refund the enrollment key’s lifetime max_mailboxes count. This keeps a
copied enrollment key from creating and deleting repeatedly to bypass its cap.
Owning agents may perform lifecycle cleanup with mailbox:create; dedicated destructive access can use
mailbox:delete. Deleting a message or thread is separate from deleting the inbox.
- Messages, threads, and search
- Domains and onboarding
- Review Loop agent contract
- Deliverability and limits
Outbound message limits
Section titled “Outbound message limits”Aim for about 1 MB of attachment files in total, with a short message body. This is practical guidance, not a guaranteed allowance for files of that size. Attachments grow during encoding, and both text and HTML bodies share the budget. The precise 1,800,000-byte limit below applies after encoding, not to file sizes on disk. A 1.5 MB file can exceed 2 MB after encoding, so 1.5 MB is not a safe attachment-size promise.
These limits apply to API, SDK, MCP and paid SMTP sends, including replies, forwards and revised drafts. They apply independently of your plan’s daily and monthly recipient quotas.
| Limit | Maximum |
|---|---|
| Recipients in one message | 50 total across To, Cc and Bcc |
| Encoded message content | 1,800,000 bytes (1.8 MB), including headers, text, HTML and attachments |
| Attachments | 20 files, sharing the same message-size budget |
Attachment files are base64 encoded for delivery, adding about 37% with line wrapping. A file’s size on disk is therefore smaller than its contribution to the message limit. A 1 MB file typically fits with a short body; a 1.4 MB file does not. Both text and HTML count when you supply both. Use a download link for larger files. There is no separate size allowance for each attachment.
Extrovert leaves extra space for its footer, unsubscribe and delivery headers; the outgoing message is checked again after these are added. The 25 MiB HTTP request-body ceiling is a transport safeguard, not a larger email allowance.
An oversized API request for an email returns HTTP 413 with code bad_request
and a size limit in the detail. Too many recipients or attachments returns HTTP
400. SMTP rejects oversized messages with 552 5.3.4; exceeding the recipient
count returns 550 5.5.3. Reduce the message before retrying. SMTP acceptance
still means the message is held for review when review is required.
Limits are checked before creating a review or reserving its recipient quota. A rejected draft revision leaves the previous draft and reservation unchanged. A revision that removes recipients releases the corresponding quota; canceling releases its unsent reservation. These limits do not guarantee acceptance by every recipient’s own mail server, which may impose a smaller limit.
Read and manage inboxes in the console
Section titled “Read and manage inboxes in the console”Select the organization and project first. Mail -> Conversations combines mail from that project’s inboxes. Mail -> Inboxes is a searchable directory: use Open inbox for one inbox’s conversations, or Manage inbox for its sender name, daily sending limit, deletion, and project transfer. Shared-domain inboxes belong to one project even though the domain itself is available to other projects.
See moving resources between projects for previews, worker access, and pending drafts.