Order mailboxes with your AI agent

Install the Inbox Insiders skill once, give your agent an API key, and ask it for mailboxes in plain words. The skill tells it to quote the cost and wait for your yes before each order.

Works withClaudeOpenAICursor

Run this in your terminal. It installs the Inbox Insiders skill for every project on this computer.

mkdir -p ~/.claude/skills/inbox-insiders && curl -fsSL https://inboxinsiders.io/skill/inbox-insiders/SKILL.md -o ~/.claude/skills/inbox-insiders/SKILL.md

Start a new Claude Code session, then ask it for mailboxes.

Give your agent an API key

Keep the key in the INBOX_INSIDERS_API_KEY environment variable, never in the chat. Orders your agent places charge the card saved on your account.

Sign in to create an API key

Getting Started

The Inbox Insiders API lets you programmatically provision SMTP and Google Workspace mailboxes for cold email infrastructure. Suggest domains, place orders, track progress, and export credentials, all via REST.

Base URL

https://inboxinsiders.io/api/v1

Pricing

$3.50/mailbox/mo + $12/domain

Rate Limit

60 requests/min per key

Pricing example: 30 mailboxes = 10 domains (3 mailboxes each) → $105/mo recurring + $120 one-time domain registration (easy mode). Same pricing for SMTP and Google Workspace.

Authentication

All API requests require a Bearer token in the Authorization header.

Authorization: Bearer ii_live_your_key_here
Get your API key: create one at the top of this page. Keys are scoped and can be revoked at any time.

Quick Start

Get mailboxes provisioned in 4 steps. All you need is an API key and a saved payment method.

1

Get domain suggestions

curl -X POST https://inboxinsiders.io/api/v1/domains/suggest \
  -H "Authorization: Bearer ii_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "brand_name": "acme", "count": 5 }'
2

Create order (charges card)

curl -X POST https://inboxinsiders.io/api/v1/instant-orders \
  -H "Authorization: Bearer ii_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "easy",
    "quantity": 30,
    "brand_name": "Acme Corp",
    "sender_name": "John Smith",
    "website_url": "https://acme.com",
    "idempotency_key": "order-001"
  }'
3

Poll until complete (30s intervals)

curl "https://inboxinsiders.io/api/v1/instant-orders?run_id=YOUR_RUN_ID" \
  -H "Authorization: Bearer ii_live_xxx"
4

Export credentials

curl "https://inboxinsiders.io/api/v1/instant-orders/export?run_id=YOUR_RUN_ID" \
  -H "Authorization: Bearer ii_live_xxx"

Endpoints

All endpoints are relative to the base URL https://inboxinsiders.io/api/v1.

Check Domain Availability

POST/api/v1/domains/check

Check if specific domains are available for purchase. Use this before placing an order with your own domain picks.

Parameters

Check Domain Availability parameters
NameTypeRequiredDescription
domainsstring[]requiredArray of domain names to check (max 50)

Request

curl -X POST https://inboxinsiders.io/api/v1/domains/check \
  -H "Authorization: Bearer ii_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "domains": ["getacme.com", "acmehq.com", "trybrand.com"]
  }'

Response (200)

{
  "results": [
    { "domain": "getacme.com", "available": true, "price_cents": 1200 },
    { "domain": "acmehq.com", "available": true, "price_cents": 1200 },
    { "domain": "trybrand.com", "available": false, "price_cents": 1200 }
  ],
  "available_count": 2,
  "unavailable_count": 1
}

Note: Max 50 domains per request

Domains are deduplicated automatically

Preview Mailbox Names

POST/api/v1/mailboxes/preview

See the exact email addresses a set of mailbox names would produce, before you order. Read-only: nothing is saved and nothing is charged. Available for private_smtp and microsoft_365 only.

Parameters

Preview Mailbox Names parameters
NameTypeRequiredDescription
quantitynumberoptionalTotal mailboxes you plan to order. Required unless domains is sent. With domains, the quantity is 3 mailboxes per domain (as on POST /instant-orders) and a different value is rejected.
mailbox_people{ first_name, last_name, count? }[]optionalPeople to name the mailboxes after. If omitted, one person is taken from sender_name.
sender_namestringoptionalUsed when mailbox_people is omitted. First word is the first name, the rest is the last name. The result is then a guide, not exact: the response says exact: false.
mailbox_formatsstring[]optionalAddress styles: "first", "first.last", "firstlast", "first.l". Defaults to all four.
domainsstring[]optionalYour domains. If omitted, placeholder domains (domain-1.example, ...) are used and domains_are_placeholders is true.
domain_countnumberoptionalHow many domains to plan for when domains is omitted. Defaults to quantity / 3, rounded up.
infrastructure_typestringoptional"private_smtp" (default) or "microsoft_365". "google_workspace" returns 422 INVALID_MAILBOX_PEOPLE: Google Workspace orders do not take approved mailbox names.

Request

curl -X POST https://inboxinsiders.io/api/v1/mailboxes/preview \
  -H "Authorization: Bearer ii_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "quantity": 3,
    "domains": ["willmanpartners.com"],
    "mailbox_people": [
      { "first_name": "Arianna", "last_name": "Martinez" },
      { "first_name": "Cassy", "last_name": "McGhee" },
      { "first_name": "Zory", "last_name": "Miller" }
    ]
  }'

Response (200)

{
  "mailboxes": [
    { "email": "arianna@willmanpartners.com", "first_name": "Arianna", "last_name": "Martinez" },
    { "email": "cassy@willmanpartners.com", "first_name": "Cassy", "last_name": "McGhee" },
    { "email": "zory@willmanpartners.com", "first_name": "Zory", "last_name": "Miller" }
  ],
  "people": [
    { "first_name": "Arianna", "last_name": "Martinez", "count": 1 },
    { "first_name": "Cassy", "last_name": "McGhee", "count": 1 },
    { "first_name": "Zory", "last_name": "Miller", "count": 1 }
  ],
  "formats": ["first", "first.last", "firstlast", "first.l"],
  "domains_are_placeholders": false,
  "exact": true
}

Note: Invalid names, counts or capacity return 422 with code INVALID_MAILBOX_PEOPLE and an errors array

google_workspace is not supported and returns 422 INVALID_MAILBOX_PEOPLE

private_smtp allows at most 5 mailboxes per domain

microsoft_365 returns people and a note instead of addresses: Microsoft 365 picks the exact addresses

exact is true when you send mailbox_people: the addresses match what is created when you pass the same mailbox_people and domains to POST /instant-orders. With only sender_name, exact is false and the list is a guide

Up to 200 domains per request. Domains are lowercased and deduplicated, and must be valid domain names

AI Domain Suggestions

POST/api/v1/domains/suggest

Generate AI-powered domain name suggestions based on your brand, with real-time availability checks.

Parameters

AI Domain Suggestions parameters
NameTypeRequiredDescription
brand_namestringoptionalBrand name (at least one of brand_name or website_url required)
website_urlstringoptionalWebsite URL to analyze
countnumberoptionalNumber of suggestions (1-30, default 10)
domain_instructionsstringoptionalCustom instructions (e.g. 'use pro suffix')

Request

curl -X POST https://inboxinsiders.io/api/v1/domains/suggest \
  -H "Authorization: Bearer ii_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "brand_name": "acme",
    "count": 10,
    "domain_instructions": "use pro suffix where possible"
  }'

Response (200)

{
  "brand_name": "acme",
  "suggestions": [
    { "domain": "getacme.com", "available": true, "price_cents": 1200 },
    { "domain": "acmepro.com", "available": true, "price_cents": 1200 },
    { "domain": "acmehq.com", "available": false, "price_cents": 1200 }
  ],
  "available_count": 8,
  "total_generated": 15
}

Note: At least one of brand_name or website_url required

count defaults to 10, max 30

Check Domain Blacklists

POST/api/v1/domains/blacklist

Check domains against 10 DNSBL blocklist zones (Spamhaus DBL, SURBL, URIBL, and more). Use this to vet sending domains before or after purchase.

Parameters

Check Domain Blacklists parameters
NameTypeRequiredDescription
domainsstring[]requiredArray of domains to check (max 25). Bare domains, URLs, and emails are accepted and normalized.

Request

curl -X POST https://inboxinsiders.io/api/v1/domains/blacklist \
  -H "Authorization: Bearer ii_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "domains": ["getacme.com", "acmehq.com"]
  }'

Response (200)

{
  "results": [
    {
      "domain": "getacme.com",
      "status": "clean",
      "listed_on": [],
      "zones_checked": 10,
      "zones_indeterminate": 6,
      "checked_at": "2026-07-09T16:00:00.000Z"
    },
    {
      "domain": "acmehq.com",
      "status": "flagged_major",
      "listed_on": [
        {
          "zone": "dbl.spamhaus.org",
          "name": "Spamhaus DBL",
          "advisory": false,
          "response": "127.0.1.2",
          "delisting_url": "https://check.spamhaus.org/"
        }
      ],
      "zones_checked": 10,
      "zones_indeterminate": 5,
      "checked_at": "2026-07-09T16:00:00.000Z"
    }
  ],
  "flagged_major_count": 1,
  "flagged_minor_count": 0,
  "clean_count": 1,
  "unknown_count": 0
}

Note: Max 25 domains per request (each domain fans out to ~10 DNS blocklist queries)

status: flagged_major = listed on an authoritative zone; flagged_minor = advisory zones only (e.g. newly-registered-domain lists); clean = verified not listed; unknown = lookups were indeterminate

"clean" is sentinel-verified: zones are only trusted for a clean verdict when their published always-listed test point resolves — no silent false-clean

Results are cached for 15 minutes

Create Order

POST/api/v1/instant-orders

Create a paid SMTP or Google Workspace mailbox order. CHARGES THE CUSTOMER'S CARD IMMEDIATELY.

Parameters

Create Order parameters
NameTypeRequiredDescription
mode"easy" | "full_control"required'easy' = auto-register domains ($12/each). 'full_control' = use your own.
infrastructure_type"private_smtp" | "google_workspace"optionalDefaults to private_smtp (instant, automated). google_workspace orders are charged then set up by our team. The response still includes run_id from the reserved run. Poll GET /instant-orders?run_id= or ?idempotency_key=.
sender_namestringrequiredFull name for mailboxes — must include first AND last name (e.g. 'John Smith'). Single-word values are rejected with VALIDATION_ERROR.
domainsstring[]optionalRequired for full_control. Optional for easy mode.
quantitynumberoptionalMailbox count for easy mode (ignored if domains provided)
brand_namestringoptionalBrand name for domain generation (easy mode)
website_urlstringrequiredWebsite URL — used for domain generation context and order metadata. Required.
idempotency_keystringoptionalUnique key to prevent duplicate orders on retry
mailbox_people{ first_name, last_name, count? }[]optionalName the mailboxes after these people (1 to 20). private_smtp and microsoft_365 only: on google_workspace it returns 422 INVALID_MAILBOX_PEOPLE, so put naming requests for those orders in special_instructions. Give every person a count, or none to split evenly; counts must add up to the mailbox total. Each person needs a different first name. Omit to name mailboxes after sender_name. Invalid input returns 422 INVALID_MAILBOX_PEOPLE before any charge. Preview the exact addresses with POST /mailboxes/preview.
mailbox_formatsstring[]optionalAddress styles to use, from "first", "first.last", "firstlast", "first.l". Defaults to all four. Only read when mailbox_people is sent. private_smtp and microsoft_365 only, like mailbox_people.
cold_emailobjectoptional{ "provider": "instantly"|"smartlead"|"reachinbox"|"emailbison"|"plusvibe", "api_key": "xxx", "workspace_url": "https://...", "workspace_id": "..." } — workspace_url is required for Email Bison. workspace_id is the 24-character PlusVibe workspace ID and is required with api_key for plusvibe. A plusvibe order with neither api_key nor workspace_id records PlusVibe as your sequencer and skips the mailbox upload; GET /instant-orders/export still returns the mailboxes. plusvibe with an api_key is not available on Google Workspace orders. Reach Inbox may send { "provider": "reachinbox", "order_ref" } from POST /sequencer-secrets instead of api_key.

Request

curl -X POST https://inboxinsiders.io/api/v1/instant-orders \
  -H "Authorization: Bearer ii_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "easy",
    "quantity": 30,
    "sender_name": "John Smith",
    "website_url": "https://acme.com",
    "brand_name": "Acme Corp",
    "idempotency_key": "order-001"
  }'

# Or pick your own pre-checked domains (easy mode, .com only):
#   "domains": ["getacme.com", "acmehq.com"]  (instead of "quantity")
# Or Google Workspace (team-fulfilled, still returns run_id):
#   "infrastructure_type": "google_workspace"

Response (201)

// SMTP (instant):
{
  "run_id": "uuid",
  "order_id": "uuid",
  "status": "running",
  "instant": true
}

// Google Workspace / manual (team-fulfilled, reserved run_id, poll it):
{
  "run_id": "uuid",
  "order_id": "uuid",
  "status": "pending_setup",
  "instant": false,
  "reason": "Google Workspace orders are provisioned by our team.",
  "domains": ["getacme.com", "acmehq.com"]
}

Note: sender_name must include both first and last name (e.g. 'John Smith') — single-word values are rejected

website_url is required — non-empty string. Missing or blank values are rejected with VALIDATION_ERROR (422)

Pricing: $3.50/mailbox/month + $12/domain (easy mode). Example: 30 mailboxes = 10 domains → $105/mo + $120 one-time

3 mailboxes per domain

Customer must have a saved Stripe payment method

Use idempotency_key to prevent duplicate charges on retry. The first write is a reserved run; a retried key returns the existing run with duplicate: true and no new charge. A still-reserved key younger than 10 minutes returns 409 IN_PROGRESS with retry_after

Failed reservations stay failed; recovery GET returns them. Support resolves those by hand — there is no automatic re-run

Easy mode + domains[]: every domain must end in .com — non-.com is rejected with VALIDATION_ERROR before any Stripe charge

Easy mode + domains[]: availability is re-checked at order time — unavailable domains are rejected before any Stripe charge (run /domains/check or /domains/suggest first)

infrastructure_type: google_workspace and full_control orders are set up by our team (instant: false) and still return run_id. Poll GET /instant-orders?run_id= or GET /instant-orders?idempotency_key=

Check Order Status

GET/api/v1/instant-orders?run_id=UUID

Poll the current status and step progress of an order. Call every 30-60 seconds after creating an order.

Parameters

Check Order Status parameters
NameTypeRequiredDescription
run_idstring (UUID)requiredThe run_id returned by create order

Request

curl "https://inboxinsiders.io/api/v1/instant-orders?run_id=YOUR_RUN_ID" \
  -H "Authorization: Bearer ii_live_xxx"

Response (200)

{
  "id": "run-uuid",
  "order_id": "order-uuid",
  "status": "running",
  "current_step": "connect_domains",
  "steps": [
    { "name": "validate_inputs", "status": "completed", "label": "Validate Inputs" },
    { "name": "connect_domains", "status": "running", "label": "Connect Domains" }
  ],
  "error_message": null,
  "started_at": "2026-04-13T...",
  "completed_at": null
}

Note: Terminal statuses: completed, completed_with_warnings, failed

Typical completion: 5-30 minutes

Use exponential backoff: 30s → 60s → 120s (cap at 2 min)

Export Credentials

GET/api/v1/instant-orders/export?run_id=UUID

Export decrypted SMTP/IMAP credentials for a completed order. Returns plaintext passwords — do not log or cache.

Parameters

Export Credentials parameters
NameTypeRequiredDescription
run_idstring (UUID)requiredThe run_id of a completed order

Request

curl "https://inboxinsiders.io/api/v1/instant-orders/export?run_id=YOUR_RUN_ID" \
  -H "Authorization: Bearer ii_live_xxx"

Response (200)

{
  "run_id": "uuid",
  "order_id": "uuid",
  "status": "completed",
  "mailboxes": [
    {
      "email": "john@getacme.com",
      "password": "decrypted-password",
      "imap_host": "imap.your-mail-host.com",
      "imap_port": 993,
      "smtp_host": "smtp.your-mail-host.com",
      "smtp_port": 465
    }
  ],
  "domains": [
    { "domain": "getacme.com", "status": "active" }
  ],
  "completed_at": "2026-04-13T..."
}

Note: Only works when status is completed or completed_with_warnings

Returns plaintext passwords — handle securely

Poll Order Status (redacted)

GET/api/v1/instant-orders/{runId}

Vendor-redacted status for a run owned by the calling API key. 404 if the run does not exist for this key. SMTP/IMAP passwords are never included; use /instant-orders/export for those.

Parameters

Poll Order Status (redacted) parameters
NameTypeRequiredDescription
runIdstring (UUID)requiredThe run_id returned by create order

Request

curl "https://inboxinsiders.io/api/v1/instant-orders/YOUR_RUN_ID" \
  -H "Authorization: Bearer ii_live_xxx"

Response (200)

{
  "id": "run-uuid",
  "order_id": "order-uuid",
  "status": "completed_with_warnings",
  "current_step": "finalize",
  "steps": [
    { "name": "validate_inputs", "index": 0, "status": "completed" },
    { "name": "connect_domains_smtp", "index": 3, "status": "completed" }
  ],
  "warnings": [
    { "code": "tool_connection_failed", "message": "A mailbox could not be connected to the sending tool." }
  ],
  "export": {
    "domains": ["getacme.com"],
    "mailboxes": [{ "email": "john@getacme.com" }]
  },
  "started_at": "2026-09-02T...",
  "completed_at": "2026-09-02T..."
}

Note: Public statuses: queued, running, completed, completed_with_warnings, failed, cancelled

held_for_review replaces queued or running while our team reviews the order before its mailboxes are created. It is not terminal: keep polling. hold_reason is a fixed explanation. The same applies to GET /instant-orders?run_id= and ?idempotency_key=

warnings[].message is a canned string keyed by code; raw pipeline text is never returned

export is present only on completed and completed_with_warnings; a failed export read returns 503 SERVICE_UNAVAILABLE with retryable: true

Recover a lost create response with GET /instant-orders?idempotency_key=YOUR_KEY before re-posting

Cancel Order

POST/api/v1/instant-orders/{runId}/cancel

Cancel an order placed with this API key, effective now. Billing for the order stops immediately with no refund and no proration. Its mailboxes are deleted the same day and auto-renew is turned off on its domains. Safe to retry.

Parameters

Cancel Order parameters
NameTypeRequiredDescription
runIdstring (UUID)requiredThe run_id returned by create order. No request body.

Request

curl -X POST "https://inboxinsiders.io/api/v1/instant-orders/YOUR_RUN_ID/cancel" \
  -H "Authorization: Bearer ii_live_xxx"

Response (200)

{
  "order_id": "order-uuid",
  "status": "pending_cancel",
  "mailboxes_pending": 6,
  "domains_auto_renew_off": 2
}

Note: Idempotent: calling it again returns 200 with the order's current state. If a call fails partway, retrying finishes the job without repeating what already happened

status is pending_cancel, or canceled once billing has fully closed. Both mean the cancel went through

mailboxes_pending counts mailboxes whose deletion has not been confirmed yet. domains_auto_renew_off counts the order's domains with auto-renew confirmed off

404 ORDER_NOT_FOUND if the run does not belong to this API key

409 IN_PROGRESS (retryable: true) while the order is still being set up, or while another cancel holds it. Nothing is changed. Retry later; an order can't be cancelled until its setup finishes

409 ORDER_NOT_READY when the order can't be cancelled by API (still awaiting payment, or it shares billing with another order). Nothing is changed. Cancel a shared-billing order from its order page in the dashboard

503 SERVICE_UNAVAILABLE (retryable: true) when a step could not finish. Retry; completed steps are not repeated

Domain registration fees are not refunded

Store a Sequencer Secret

POST/api/v1/sequencer-secrets

Hand over a Reach Inbox workspace key as an opaque, single-use reference. The secret is never returned. Pass the order_ref on POST /instant-orders as cold_email.order_ref.

Parameters

Store a Sequencer Secret parameters
NameTypeRequiredDescription
provider"reachinbox"requiredSequencer provider. Only reachinbox is accepted today.
secretstringrequiredWorkspace API key. Stored encrypted; never logged or returned.
idempotency_keystringrequiredReplay returns the same order_ref.
order_idempotency_keystringoptionalOptional order idempotency key this secret may later attach to.

Request

curl -X POST https://inboxinsiders.io/api/v1/sequencer-secrets \
  -H "Authorization: Bearer ii_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "reachinbox",
    "secret": "YOUR_WORKSPACE_KEY",
    "idempotency_key": "secret-001",
    "order_idempotency_key": "order-001"
  }'

Response (201)

{
  "order_ref": "uuid",
  "status": "unattached",
  "expires_at": "2026-09-03T...",
  "handoff_enabled": false
}

Note: Unattached refs expire after 24 hours and are revoked by a sweep

GET /sequencer-secrets?idempotency_key= recovers a lost order_ref

GET /sequencer-secrets/{ref} returns { status, provider, expires_at } only. After resolve, status is revoked

order_ref on POST /instant-orders ships disabled (409 SEQUENCER_SECRET_HANDOFF_DISABLED) until order_ref handoff is turned on. Minting a ref is always allowed; handoff_enabled reports the gate.

CLI & skill

Two zero-setup ways to use the API: a command-line tool and a Claude Code skill. Both talk to the same REST endpoints and support SMTP and Google Workspace orders.

Claude Code skill (one command)

mkdir -p ~/.claude/skills/inbox-insiders && curl -fsSL https://inboxinsiders.io/skill/inbox-insiders/SKILL.md -o ~/.claude/skills/inbox-insiders/SKILL.md

Set INBOX_INSIDERS_API_KEY in your environment, then ask Claude to “order 30 SMTP mailboxes for acme.com”. The skill teaches it the full API, pricing, idempotency, and Google Workspace behavior.

CLI (Node 18+, zero dependencies)

curl -fsSL https://inboxinsiders.io/cli/inbox-insiders.mjs -o /usr/local/bin/inbox-insiders && chmod +x /usr/local/bin/inbox-insiders
export INBOX_INSIDERS_API_KEY=ii_live_YOUR_KEY_HERE
inbox-insiders help

CLI commands

check <domain...>
Description
Check domain availability (max 50)
suggest --brand acme
Description
AI domain suggestions with pricing
order --yes
Description
Create SMTP or Google mailbox order (charges card; --type google_workspace)
status <run_id>
Description
Poll order progress (SMTP instant orders)
export <run_id>
Description
Get mailbox credentials (completed orders)

LLM Instructions

Claude Code

With the skill installed (see above), Claude Code can provision mailboxes via natural language:

Example prompts:

  • "Check if getacme.com is available"
  • "Suggest 5 domains for the brand Acme Corp"
  • "Create an order for getacme.com and acmehq.com, sender name John Smith"
  • "Check the status of order run_id abc-123"
  • "Export credentials for the completed order"

Other AI Models

For any other AI agent, use the machine-readable API reference:

curl https://inboxinsiders.io/llms.txt

The /llms.txt endpoint returns a plain-text API reference optimized for LLM context windows (~3KB). Feed it as system context to any AI model.

Agent Workflow

The typical AI agent flow for provisioning mailboxes:

1. POST /domains/suggest (brand_name="acme") → pick available domains

2. POST /instant-orders (mode="easy", domains=[...], sender_name="...") → get run_id

3. GET /instant-orders?run_id=... → poll every 30s until terminal

4. GET /instant-orders/export?run_id=... → get SMTP/IMAP credentials

SDK / Client Libraries

Full working examples for the complete order flow: suggest → order → poll → export.

import requests
import time

API_KEY = "ii_live_xxx"
BASE = "https://inboxinsiders.io/api/v1"
headers = {"Authorization": f"Bearer {API_KEY}"}

# 1. Suggest domains
suggestions = requests.post(f"{BASE}/domains/suggest",
    headers=headers,
    json={"brand_name": "acme", "count": 5}
).json()["suggestions"]

available = [s["domain"] for s in suggestions if s["available"]]

# 2. Create order
order = requests.post(f"{BASE}/instant-orders",
    headers=headers,
    json={
        "mode": "easy",
        "domains": available[:3],
        "sender_name": "John Smith",
        "website_url": "https://acme.com",
        "idempotency_key": "py-order-001"
    }
).json()

run_id = order["run_id"]
print(f"Order created: {run_id}")

# 3. Poll until complete
while True:
    status = requests.get(f"{BASE}/instant-orders?run_id={run_id}",
        headers=headers).json()
    print(f"Status: {status['status']} - Step: {status.get('current_step', 'n/a')}")
    if status["status"] in ("completed", "completed_with_warnings", "failed"):
        break
    time.sleep(30)

# 4. Export credentials
if status["status"] != "failed":
    creds = requests.get(f"{BASE}/instant-orders/export?run_id={run_id}",
        headers=headers).json()
    for m in creds["mailboxes"]:
        print(f"{m['email']} - {m['smtp_host']}:{m['smtp_port']}")

Error Reference

All errors return: { "error": { "code": "...", "message": "..." } }

Error codes
CodeHTTPDescriptionHow to Handle
INVALID_API_KEY401Bad or revoked API keyCheck your API key in Settings → API Keys
API_KEY_EXPIRED401API key past expiry dateGenerate a new API key
MISSING_SCOPE403Key lacks instant_orders scopeCreate a new key with the required scope
RATE_LIMITED429Too many requests (default: 60/min)Back off and retry after the rate limit window
INVALID_REQUEST400Malformed request bodyCheck JSON structure and required fields
VALIDATION_ERROR422Field validation failedCheck error message for specific field issues

Common messages

  • sender_name (empty): “Enter your sender name (first and last name)”
  • sender_name (single word): “Enter both a first and last name (e.g., John Smith)”
  • website_url: “website_url is required”
  • domains (non-.com in easy mode): “Only .com domains are supported when supplying domains[] in easy mode. Rejected: <list>. Submit only .com domains that are confirmed available.”
  • domains (unavailable in easy mode): “The following domains are not available for registration: <list>. Use /v1/domains/check or /v1/domains/suggest first to find available .com domains.”
INVALID_MAILBOX_PEOPLE422mailbox_people or mailbox_formats failed validationRead the errors array in the response, fix the names or counts, and resend. Nothing was charged.

Common messages

  • mailbox_people (duplicate first name): “Two people share the first name Sam. Give each person a different first name.”
  • mailbox_people (counts): “The counts add up to 5 but the order is for 3 mailboxes.”
  • mailbox_people (google_workspace): “Approved mailbox names (mailbox_people and mailbox_formats) are available for private_smtp and microsoft_365 orders only. For google_workspace orders, leave them out and put any naming requests in special_instructions.”
IDEMPOTENCY_CONFLICT409The idempotency_key was already used with different mailbox_people or mailbox_formatsUse a new idempotency_key to place a different order, or resend the original request to replay it
FEATURE_UNAVAILABLE503A requested option is not available right nowNothing was charged. Retry without the option, or try again later
PAYMENT_METHOD_REQUIRED402No payment method on fileAdd a card at Settings → Billing
PAYMENT_FAILED402Card declined or charge failedUpdate payment method and retry
ORDER_NOT_FOUND404Run not found or wrong customerVerify the run_id belongs to your account
ORDER_NOT_READY409Order still processing (export)Wait for status to be completed, then retry
SEQUENCER_SECRET_HANDOFF_DISABLED409cold_email.order_ref is not enabled yetSend cold_email.api_key until order_ref handoff is turned on. handoff_enabled on POST /sequencer-secrets shows when it is
GONE410Sequencer secret already consumed, revoked, or expiredMint a new order_ref with POST /sequencer-secrets
INTERNAL_ERROR500Unexpected server errorRetry after a short delay.

Changelog

v1.7.02026-10-03

PlusVibe support

  • NewPOST /instant-orders accepts plusvibe as a cold_email provider. Send api_key plus workspace_id, the 24-character ID of your PlusVibe workspace, and we upload the mailboxes and start warmup. A missing or malformed workspace_id returns a validation error before any charge
  • NewSend { "provider": "plusvibe" } with no api_key and no workspace_id to record PlusVibe as your sequencer without an upload. GET /instant-orders/export still returns the mailboxes so you can import them yourself
  • Improvedplusvibe with an api_key is available on private_smtp orders only. google_workspace orders that send it are refused, the same as reachinbox
v1.6.02026-10-01

Name your mailboxes

  • NewPOST /instant-orders accepts optional mailbox_people and mailbox_formats to name mailboxes after specific people, on private_smtp and microsoft_365 orders. Invalid input returns 422 INVALID_MAILBOX_PEOPLE before any charge
  • NewAdded POST /mailboxes/preview to see the exact addresses before ordering, for private_smtp and microsoft_365. Read-only, no charge
  • Improvedgoogle_workspace orders do not take mailbox_people or mailbox_formats and return 422 INVALID_MAILBOX_PEOPLE if they are sent. Put naming requests for those orders in special_instructions
v1.5.12026-10-01

held_for_review status

  • NewOrder status can now be held_for_review, in place of queued or running, when our team needs to review an order before its mailboxes are created. It is not terminal, so keep polling. The response includes hold_reason with a short explanation. Applies to GET /instant-orders/{runId}, ?run_id= and ?idempotency_key=
v1.5.02026-09-02

Durable idempotency, redacted status, sequencer secrets

  • NewGET /instant-orders/{runId} — vendor-redacted poll (queued/running/completed/completed_with_warnings/failed/cancelled). Export of domain names and mailbox emails only on terminal success; passwords stay on /export
  • NewGET /instant-orders?idempotency_key= recovers a lost create response for the calling key (404 if none) so a client can look up before re-posting
  • ImprovedPOST /instant-orders reserves (api_key_id, idempotency_key) before any Stripe or order write. Google and full_control responses include that run_id. Poll GET /instant-orders?run_id= or ?idempotency_key=. A still-reserved key younger than 10 minutes returns 409 IN_PROGRESS with retry_after; a failed reservation is returned on replay and is not re-charged
  • NewPOST /sequencer-secrets stores a Reach Inbox workspace key and returns an opaque order_ref (response includes handoff_enabled). The order_ref handoff on POST /instant-orders ships disabled: 409 SEQUENCER_SECRET_HANDOFF_DISABLED until order_ref handoff is turned on, which handoff_enabled reports. Attach happens in the reservation. GET /{ref} after resolve returns status revoked
v1.4.02026-07-09

Domain Blacklist Checking

  • NewNew POST /domains/blacklist — check up to 25 domains against 10 DNSBL blocklist zones (Spamhaus DBL, SURBL, URIBL, and more) with per-zone listing details and delisting links
  • ImprovedBlocklist lookups now fall back to a second DoH resolver on transient failures, and "clean" verdicts are sentinel-verified — a blocked or misconfigured resolver can never report a false clean
  • ImprovedCLI v1.2.0 adds the `blacklist` command; the Claude skill documents the new endpoint
v1.3.02026-07-05

Google Workspace Orders, CLI & Claude Skill

  • NewPOST /instant-orders accepts infrastructure_type: "google_workspace" — Google mailbox orders via API (charged, then team-fulfilled; response has instant:false and no run_id)
  • NewNew installable CLI (inboxinsiders.io/cli/inbox-insiders.mjs) and Claude Code skill (inboxinsiders.io/skill/inbox-insiders/SKILL.md)
  • ImprovedIdempotency now also covers team-fulfilled orders — duplicate idempotency_key returns the existing order (duplicate:true) instead of charging again
  • ImprovedTeam-fulfilled order responses include the purchased domains[]
  • BreakingMCP server retired — use the Claude skill or CLI instead (same capabilities, no build step)
v1.2.12026-04-28

Easy-mode domain validation hardening

  • ImprovedEasy mode + domains[]: non-.com domains are rejected with VALIDATION_ERROR (422) before any Stripe charge — easy mode only sells .com domains
  • ImprovedEasy mode + domains[]: each domain is re-checked for availability at order time and rejected with VALIDATION_ERROR before any Stripe charge if unavailable
  • FixedBad payloads no longer burn idempotency keys — validation gates run before idempotency lookup and Stripe subscription creation
v1.2.02026-04-13

MCP Server & LLM Documentation

  • NewAdded MCP server for Claude Code integration (5 tools)
  • NewAdded /llms.txt route for LLM-friendly API reference
  • ImprovedEnhanced API documentation with Quick Start, Polling Strategy, and Mode Comparison sections
v1.1.02026-04-01

Domain Selection for Easy Mode

  • NewEasy mode now supports passing specific domains[] instead of just quantity
  • NewAdded POST /domains/check endpoint for domain availability checking
  • NewAdded POST /domains/suggest endpoint for AI domain suggestions
  • ImprovedDomain availability is re-verified at order time to prevent stale purchases
v1.0.02026-03-15

Initial API Release

  • NewPOST /instant-orders — Create paid SMTP mailbox orders
  • NewGET /instant-orders — Poll order status with step progress
  • NewGET /instant-orders/export — Export decrypted credentials
  • NewAPI key management with scoped access and rate limiting
  • NewIdempotency support via idempotency_key parameter