Skip to content

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.

Every inbox has:

  • an opaque id such as pmbx_…, which is the stable API path key;
  • an email address, accepted as a project-local path alias;
  • fixed org_id, project_id, and agent_id ownership;
  • a lifecycle status;
  • an effective rolling 24-hour recipient limit;
  • a read-only direct_smtp_enabled status 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:

AccountAddress domain
Paid account without a custom domainextrovertmail.com
Free account, when free signup is enabledfree.extrovertmail.com
Account with a verified custom domainThe 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.

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",
});
  1. Create. Extrovert creates the receiving account, registers the authenticated sender, seals the connection credential, and returns the inbox. POST /v1/inboxes

  2. Inspect. Fetch the inbox before sending. The single-inbox response includes effective_review_policy; list responses do not.

  3. 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.

  4. Manage. Update the display name, webhook, metadata, or effective daily limit when the key has the required permission.

  5. 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.

PolicyBehavior
require_reviewEvery send, reply, and forward needs an intent and normally waits for human review
allow_directA bare outbound request may send immediately; an explicit review request still queues
auto_send_graduatedA 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_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 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.

MethodUse it when
Messages and threadsYou need bounded lists, search, read state, folders, or conversation history
WebhooksA service needs signed push delivery
wait_for_emailA 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.

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.

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.