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.
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.
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/v1Pricing
$3.50/mailbox/mo + $12/domain
Rate Limit
60 requests/min per key
Authentication
All API requests require a Bearer token in the Authorization header.
Authorization: Bearer ii_live_your_key_here
Quick Start
Get mailboxes provisioned in 4 steps. All you need is an API key and a saved payment method.
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 }'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"
}'Poll until complete (30s intervals)
curl "https://inboxinsiders.io/api/v1/instant-orders?run_id=YOUR_RUN_ID" \ -H "Authorization: Bearer ii_live_xxx"
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
/api/v1/domains/checkCheck if specific domains are available for purchase. Use this before placing an order with your own domain picks.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| domains | string[] | required | Array 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
/api/v1/mailboxes/previewSee 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
| Name | Type | Required | Description |
|---|---|---|---|
| quantity | number | optional | Total 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? }[] | optional | People to name the mailboxes after. If omitted, one person is taken from sender_name. |
| sender_name | string | optional | Used 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_formats | string[] | optional | Address styles: "first", "first.last", "firstlast", "first.l". Defaults to all four. |
| domains | string[] | optional | Your domains. If omitted, placeholder domains (domain-1.example, ...) are used and domains_are_placeholders is true. |
| domain_count | number | optional | How many domains to plan for when domains is omitted. Defaults to quantity / 3, rounded up. |
| infrastructure_type | string | optional | "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
/api/v1/domains/suggestGenerate AI-powered domain name suggestions based on your brand, with real-time availability checks.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| brand_name | string | optional | Brand name (at least one of brand_name or website_url required) |
| website_url | string | optional | Website URL to analyze |
| count | number | optional | Number of suggestions (1-30, default 10) |
| domain_instructions | string | optional | Custom 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
/api/v1/domains/blacklistCheck domains against 10 DNSBL blocklist zones (Spamhaus DBL, SURBL, URIBL, and more). Use this to vet sending domains before or after purchase.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| domains | string[] | required | Array 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
/api/v1/instant-ordersCreate a paid SMTP or Google Workspace mailbox order. CHARGES THE CUSTOMER'S CARD IMMEDIATELY.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| mode | "easy" | "full_control" | required | 'easy' = auto-register domains ($12/each). 'full_control' = use your own. |
| infrastructure_type | "private_smtp" | "google_workspace" | optional | Defaults 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_name | string | required | Full name for mailboxes — must include first AND last name (e.g. 'John Smith'). Single-word values are rejected with VALIDATION_ERROR. |
| domains | string[] | optional | Required for full_control. Optional for easy mode. |
| quantity | number | optional | Mailbox count for easy mode (ignored if domains provided) |
| brand_name | string | optional | Brand name for domain generation (easy mode) |
| website_url | string | required | Website URL — used for domain generation context and order metadata. Required. |
| idempotency_key | string | optional | Unique key to prevent duplicate orders on retry |
| mailbox_people | { first_name, last_name, count? }[] | optional | Name 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_formats | string[] | optional | Address 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_email | object | optional | { "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
/api/v1/instant-orders?run_id=UUIDPoll the current status and step progress of an order. Call every 30-60 seconds after creating an order.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| run_id | string (UUID) | required | The 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
/api/v1/instant-orders/export?run_id=UUIDExport decrypted SMTP/IMAP credentials for a completed order. Returns plaintext passwords — do not log or cache.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| run_id | string (UUID) | required | The 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)
/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
| Name | Type | Required | Description |
|---|---|---|---|
| runId | string (UUID) | required | The 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
/api/v1/instant-orders/{runId}/cancelCancel 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
| Name | Type | Required | Description |
|---|---|---|---|
| runId | string (UUID) | required | The 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
/api/v1/sequencer-secretsHand 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
| Name | Type | Required | Description |
|---|---|---|---|
| provider | "reachinbox" | required | Sequencer provider. Only reachinbox is accepted today. |
| secret | string | required | Workspace API key. Stored encrypted; never logged or returned. |
| idempotency_key | string | required | Replay returns the same order_ref. |
| order_idempotency_key | string | optional | Optional 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
- Description
- Check domain availability (max 50)
- Description
- AI domain suggestions with pricing
- Description
- Create SMTP or Google mailbox order (charges card; --type google_workspace)
- Description
- Poll order progress (SMTP instant orders)
- 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": "..." } }
| Code | HTTP | Description | How to Handle |
|---|---|---|---|
| INVALID_API_KEY | 401 | Bad or revoked API key | Check your API key in Settings → API Keys |
| API_KEY_EXPIRED | 401 | API key past expiry date | Generate a new API key |
| MISSING_SCOPE | 403 | Key lacks instant_orders scope | Create a new key with the required scope |
| RATE_LIMITED | 429 | Too many requests (default: 60/min) | Back off and retry after the rate limit window |
| INVALID_REQUEST | 400 | Malformed request body | Check JSON structure and required fields |
| VALIDATION_ERROR | 422 | Field validation failed | Check error message for specific field issues |
Common messages
| |||
| INVALID_MAILBOX_PEOPLE | 422 | mailbox_people or mailbox_formats failed validation | Read the errors array in the response, fix the names or counts, and resend. Nothing was charged. |
Common messages
| |||
| IDEMPOTENCY_CONFLICT | 409 | The idempotency_key was already used with different mailbox_people or mailbox_formats | Use a new idempotency_key to place a different order, or resend the original request to replay it |
| FEATURE_UNAVAILABLE | 503 | A requested option is not available right now | Nothing was charged. Retry without the option, or try again later |
| PAYMENT_METHOD_REQUIRED | 402 | No payment method on file | Add a card at Settings → Billing |
| PAYMENT_FAILED | 402 | Card declined or charge failed | Update payment method and retry |
| ORDER_NOT_FOUND | 404 | Run not found or wrong customer | Verify the run_id belongs to your account |
| ORDER_NOT_READY | 409 | Order still processing (export) | Wait for status to be completed, then retry |
| SEQUENCER_SECRET_HANDOFF_DISABLED | 409 | cold_email.order_ref is not enabled yet | Send cold_email.api_key until order_ref handoff is turned on. handoff_enabled on POST /sequencer-secrets shows when it is |
| GONE | 410 | Sequencer secret already consumed, revoked, or expired | Mint a new order_ref with POST /sequencer-secrets |
| INTERNAL_ERROR | 500 | Unexpected server error | Retry after a short delay. |
Changelog
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
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
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=
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
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
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)
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
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
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
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