Quickstart

Provision an inbox, send it a test email, receive the arrival, and read the message — the full provision → receive → read loop in REST, TypeScript, Python, and the CLI.

This quickstart walks the full provision → receive → read loop end to end:

  1. Provision — create an inbox and get a live email address.
  2. Receive — send a real email to that address and be notified it arrived.
  3. Read — fetch the thread and read the message.

Every step is shown in REST (cURL), TypeScript, Python, and the CLI — pick your surface. The whole loop takes a couple of minutes.

Before you start

You need an API key. If you already have one (from onboarding or the dashboard), skip ahead. Otherwise, provision an account entirely in code with the two-step signup flow.

Sign up

sign_up creates a tenant, a first inbox, and a first API key, then emails a 6-digit code to the address you give it. It is the one unauthenticated endpoint — you use it to obtain your first key.

curl -X POST https://app.theinboxagents.com/api/v1/sign_up \
  -H "Content-Type: application/json" \
  -d '{ "human_email": "you@example.com" }'
const res = await fetch("https://app.theinboxagents.com/api/v1/sign_up", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ human_email: "you@example.com" }),
});
const { tenant_id, inbox_id, api_key } = await res.json();
// Store api_key now — it is shown once and never retrievable again.
import requests

res = requests.post(
    "https://app.theinboxagents.com/api/v1/sign_up",
    json={"human_email": "you@example.com"},
)
data = res.json()
# data["api_key"] is shown once — store it now.
inboxagents agent sign-up --human-email you@example.com

The response carries a one-time api_key (an ia_… secret). Store it now — it is never returned again.

Verify

Enter the 6-digit code from the email to activate the account and lift it off the restricted new-account limits.

curl -X POST https://app.theinboxagents.com/api/v1/verify \
  -H "Content-Type: application/json" \
  -d '{ "otp_code": "123456" }'
await fetch("https://app.theinboxagents.com/api/v1/verify", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ otp_code: "123456" }),
});
requests.post(
    "https://app.theinboxagents.com/api/v1/verify",
    json={"otp_code": "123456"},
)
inboxagents agent verify --otp-code 123456

Store your key in an environment variable

Every example below reads the key from INBOXAGENTS_API_KEY. Export it once and never commit it:

export INBOXAGENTS_API_KEY="ia_your_secret_here"

1. Provision an inbox

Create an inbox. Every field is optional — omit username and you get a readable random address on agents.theinboxagents.com. The response includes the live email and the inbox's inbox_id (an inb_… id) — you'll need the id to read mail later.

curl -X POST https://app.theinboxagents.com/api/v1/inboxes \
  -H "Authorization: Bearer $INBOXAGENTS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "display_name": "Support Bot" }'
const key = process.env.INBOXAGENTS_API_KEY!;
const base = "https://app.theinboxagents.com/api/v1";

const res = await fetch(`${base}/inboxes`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${key}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ display_name: "Support Bot" }),
});
const inbox = await res.json();
console.log(inbox.email); // e.g. brave-otter@agents.theinboxagents.com
import os, requests

key = os.environ["INBOXAGENTS_API_KEY"]
base = "https://app.theinboxagents.com/api/v1"
auth = {"Authorization": f"Bearer {key}"}

inbox = requests.post(
    f"{base}/inboxes",
    headers=auth,
    json={"display_name": "Support Bot"},
).json()
print(inbox["email"])  # e.g. brave-otter@agents.theinboxagents.com
inboxagents inboxes create --display-name "Support Bot"
Response
{
  "inbox_id": "inb_8f2a1c9d",
  "email": "brave-otter@agents.theinboxagents.com",
  "display_name": "Support Bot",
  "client_id": null,
  "metadata": {},
  "created_at": "2026-07-06T12:00:00Z",
  "updated_at": "2026-07-06T12:00:00Z"
}

2. Receive an email

Send a real email to the inbox's address from any mail client — subject and body of your choosing. InboxAgents receives it, threads it, and stores the message.

To be notified the moment it arrives, use one of two real-time surfaces:

  • Webhook — register a URL and get a signed POST when a message lands.
  • WebSocket — hold a live connection and stream arrivals.

Register a webhook so your agent is pushed each new message:

curl -X POST https://app.theinboxagents.com/api/v1/webhooks \
  -H "Authorization: Bearer $INBOXAGENTS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://your-app.example.com/inboxagents/webhook" }'
await fetch(`${base}/webhooks`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${key}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ url: "https://your-app.example.com/inboxagents/webhook" }),
});
requests.post(
    f"{base}/webhooks",
    headers=auth,
    json={"url": "https://your-app.example.com/inboxagents/webhook"},
)
inboxagents webhooks create --url https://your-app.example.com/inboxagents/webhook

When a message arrives, your endpoint receives a signed event carrying the inbox_id, thread_id, and message_id. Verify the signature (the webhook signing secret is a whsec_… value returned when you create the webhook), then use those ids to read the message in step 3.

No webhook endpoint handy for testing? Skip the notification and just poll — list the inbox's threads (step 3) a few seconds after sending. The message is already stored; the webhook only tells you when it landed.

3. Read the message

List the inbox's threads (newest first), then fetch the message to read its content and headers. Threads, messages, and attachments are all addressed as subresources of the inbox that owns them.

# List threads in the inbox
curl https://app.theinboxagents.com/api/v1/inboxes/inb_8f2a1c9d/threads \
  -H "Authorization: Bearer $INBOXAGENTS_API_KEY"

# Read a single message
curl https://app.theinboxagents.com/api/v1/inboxes/inb_8f2a1c9d/messages/msg_5b3e7a10 \
  -H "Authorization: Bearer $INBOXAGENTS_API_KEY"
const inboxId = "inb_8f2a1c9d";

// List threads (newest first)
const threads = await fetch(`${base}/inboxes/${inboxId}/threads`, {
  headers: { Authorization: `Bearer ${key}` },
}).then((r) => r.json());

const latest = threads.threads[0];

// Read the message
const message = await fetch(
  `${base}/inboxes/${inboxId}/messages/${latest.last_message_id}`,
  { headers: { Authorization: `Bearer ${key}` } },
).then((r) => r.json());

console.log(message.subject, message.text);
inbox_id = "inb_8f2a1c9d"

# List threads (newest first)
threads = requests.get(
    f"{base}/inboxes/{inbox_id}/threads", headers=auth
).json()

latest = threads["threads"][0]

# Read the message
message = requests.get(
    f"{base}/inboxes/{inbox_id}/messages/{latest['last_message_id']}",
    headers=auth,
).json()

print(message["subject"], message["text"])
# List threads
inboxagents inboxes:threads list --inbox-id inb_8f2a1c9d

# Read a message
inboxagents inboxes:messages get \
  --inbox-id inb_8f2a1c9d --message-id msg_5b3e7a10

That's the whole loop — you provisioned an inbox, received a real email, and read it back. If the message has attachments, fetch each one's bytes from the attachment download endpoint.

Where to next

On this page