Create an inbox
Already connected through MCP? Use the short procedure below; no SDK is needed.
Otherwise choose your host and account path first.
Creating an inbox requires mailbox:create within the intended project or
organization. A selected-inbox grant excludes new inboxes. A limited agent key’s
organization and project are fixed; do not invent a tenant in the request.
With connected MCP
Section titled “With connected MCP”- Call
whoamiand confirm the intended project and create permission. - Read the current
create_inboxschema. Supply the requested sender name, optional address/domain, and a stableclient_idfor this creation intent. Reuse that identifier after an uncertain result instead of creating a duplicate. - Report the returned inbox ID/address only after creation succeeds. A quota or permission error is not success and does not authorize a plan upgrade.
- Read its effective review policy before any separately requested send.
For an intended new account, signup creates the initial inbox; do not create an extra inbox to finish that setup.
Create the inbox
Section titled “Create the inbox”Omit username and domain to use extrovertmail.com on a paid account. Free accounts will use
free.extrovertmail.com when free signup is enabled. Add a stable idempotency value when the same
request may be retried.
Use the private HTTPS request pattern,
with POST https://api.extrovert.dev/v1/inboxes, a stable Idempotency-Key, and:
{ "display_name": "Support agent" }The 201 response includes an opaque id, address, project and organization ids, the effective
daily recipient limit, and direct_smtp_enabled. It does not return a password unless a paid caller
explicitly requests credentials with the separate mailbox:credentials permission. Treat the opaque
id as the stable path key. The address is also accepted as a project-local alias.
npm install @extrovert.dev/sdkimport { Extrovert } from "@extrovert.dev/sdk";
const extrovert = new Extrovert({ apiKey: process.env.EXTROVERT_API_KEY! });const inbox = await extrovert.inboxes.create({ display_name: "Support agent", client_id: "support-primary",});
console.log(inbox.id);console.log(inbox.address);inboxes.create() returns an InboxHandle with methods such as send, reply, messages,
threads, waitForEmail, update, and delete.
Connect the MCP client first, then call:
{ "name": "create_inbox", "arguments": { "display_name": "Support agent", "client_id": "support-primary" }}The structured result includes the same inbox object as the REST response.
Read the review policy
Section titled “Read the review policy”Fetch the inbox before the first outbound request. The single-inbox response includes
effective_review_policy; list responses omit it.
await inbox.refresh();console.log(inbox.record?.effective_review_policy);New accounts use require_review. Under that policy:
- every send, reply, and forward needs
intent.summary; - a request without intent returns
422 intent_required, with nothing sent or queued; - a valid request normally returns
202 queued_for_reviewand anrr_...review id; - delivery finishes only after a terminal review event or a closed review record.
Agents can read the policy but cannot widen it.
Submit outbound mail
Section titled “Submit outbound mail”curl -sS -X POST "$EXTROVERT_API_BASE_URL/v1/inboxes/$INBOX_ID/send" \ -H "Authorization: Bearer $EXTROVERT_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: support-online-001" \ -d '{ "to": ["ops@acme.test"], "subject": "Support inbox ready", "text": "The support inbox is ready.", "intent": { "summary": "Tell operations that the support inbox is ready" } }'const outcome = await inbox.send({ to: "ops@acme.test", subject: "Support inbox ready", text: "The support inbox is ready.", intent: { summary: "Tell operations that the support inbox is ready" }, idempotency_key: "support-online-001",});{ "name": "send_email", "arguments": { "inbox": "pmbx_...", "to": ["ops@acme.test"], "subject": "Support inbox ready", "text": "The support inbox is ready.", "intent": { "summary": "Tell operations that the support inbox is ready" }, "client_id": "support-online-001" }}Read incoming mail
Section titled “Read incoming mail”curl -sS "$EXTROVERT_API_BASE_URL/v1/inboxes/$INBOX_ID/messages?unread=true" \ -H "Authorization: Bearer $EXTROVERT_API_KEY"const { items: messages } = await inbox.messages({ unread: true });const { items: threads } = await inbox.threads();{ "name": "read_messages", "arguments": { "inbox": "pmbx_...", "unread_only": true }}Message reads expose source-faithful text and html MIME alternatives plus nullable
extracted_text and extracted_html derivatives. Neither source format is synthesized from the
other. Use the source fields when fidelity matters and the extracted fields for concise reading.
Flow summary
Section titled “Flow summary”-
Connect with OAuth or a limited agent key.
-
Create an inbox. POST /v1/inboxes
-
Read
effective_review_policyfrom the single-inbox response. -
Submit outbound mail with an intent and monitor the returned review id.
-
Receive through messages, threads, webhooks, or
wait_for_email.