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 |
Free signup is currently disabled. 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.
Raw SMTP bypasses review, suppression and contact-list checks, unsubscribe injection, and platform accounting. API, SDK, and MCP sends still follow the Review Loop even when direct SMTP is enabled.
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.