InboxSpec home · Browse all documentation

Start with one test email

Copy a test address, send an email, and find its verification code. Then add the same flow to your tests.

Create a free account · Sign in

See your first email

Start in the browser. No terminal or package installation needed.

  1. 1

    Copy test addressOpen your project’s Inboxes page and choose Copy test address.

  2. 2

    Send an emailUse your app or email client. Include “Your code is 123456” in the message.

  3. 3

    Find the codeThe inbox appears when mail arrives. Open it to read the full message and copy the code.

Open inboxes

Read text or HTML directly in the inbox. When you’re ready to automate, use the JavaScript example below or choose Python, Go, Java, C#, PHP, Ruby or curl.

Automate it with JavaScript · no packages needed

Your first email test in JavaScript

Use Node.js 24 or newer. Create a Local development API key in your project’s Credentials page. Save it in an ignored .env file beside this script as INBOXSPEC_API_KEY=your-key. Keep that file out of source control and never put the key in browser code.

Save this as first-email.mjs. It creates a fresh test inbox, waits for a code, and prints the email’s text. No SDK or private repository access is required.

// Save as first-email.mjs. Requires Node.js 24+; no packages to install.
const apiUrl = process.env.INBOXSPEC_API_URL || "https://api.inboxspec.com";
const apiKey = process.env.INBOXSPEC_API_KEY;
if (!apiKey) throw new Error("Set INBOXSPEC_API_KEY to your project API key first.");

async function request(path, body) {
  const response = await fetch(new URL(path, apiUrl), {
    method: body === undefined ? "GET" : "POST",
    headers: { Authorization: "Bearer " + apiKey, "Content-Type": "application/json" },
    body: body === undefined ? undefined : JSON.stringify(body),
    signal: AbortSignal.timeout(70_000),
  });
  if (!response.ok) {
    // An HTTP error is different from a successful wait that found no email.
    const problem = await response.json().catch(() => null);
    throw Object.assign(new Error("HTTP " + response.status + ": check the API error reference before retrying."), {
      code: problem?.error?.code,
    });
  }
  return response;
}

const runId = "first-" + crypto.randomUUID();
const inbox = await (await request("/v1/inboxes/for-run", {
  run_id: runId, retention_seconds: 600,
})).json();
if (typeof inbox.address !== "string") throw new Error("No inbox address returned.");
console.log("Run ID:", runId);
console.log("Send a test email containing 'Your code is 123456' to: " + inbox.address);
console.log("Waiting up to 60 seconds…");
const result = await (await request("/v1/messages/wait", {
  inbox: inbox.address, match: { has_code: true }, timeout_ms: 60_000,
})).json();
if (result.status === "timeout") {
  console.log("No matching email. Check the address and your sender, then try a new run.");
  console.log({ reason: result.reason, arrivals: result.non_matching_arrivals, hint: result.hint });
  process.exitCode = 1;
} else if (result.status === "matched" && typeof result.message?.id === "string") {
  console.log("Code candidates:", result.message.codes);
  const bodyPath = "/v1/messages/" + encodeURIComponent(result.message.id) + "/body?format=";
  let body;
  try {
    body = await request(bodyPath + "text");
  } catch (error) {
    if (error.code !== "unsupported_format") throw error;
    console.log("This email is HTML-only. Email HTML:");
    body = await request(bodyPath + "html");
  }
  console.log(await body.text());
} else {
  throw new Error("Unexpected wait response. Check the API error reference.");
}
// Messages expire after ten minutes; the inbox remains until explicitly deleted. Accepted messages still count toward usage.

Run in the same folder:

node --env-file=.env first-email.mjs

Send a plain-text email to the printed address while the script waits. Expected result: Code candidates: [ '123456' ] followed by your email’s text. A timeout sets a failing exit code and shows what to check; HTTP errors remain separate.

For an automated test, replace the manual send with your app’s signup action after inbox creation, then assert the code your test expects. Each execution creates a separate inbox. Its messages expire after ten minutes; delete the inbox explicitly when finished. Mail without a text part returns unsupported_format; use the supported format from the API reference.

Use curl to test, inspect or clean up

  • Your first email

    Receive your first verification code with JavaScript/TypeScript, Python, Java or Bash/curl.

  • Inspecting messages

    Read text, HTML, links and attachments after a matching email arrives.

  • Cleaning up

    Remove only your test run after producers and waits have finished.

Account and password help

Register with your email. Use at least 12 characters including an uppercase letter, a lowercase letter and a number. Symbols are optional. Confirm your email with the code we send you.

Already registered? Choose Sign in. To reset a password, choose Forgot your password on the sign-in page.

SDK, CLI and MCP setup

Connect your agent to hosted InboxSpec with a project key; no local MCP server is needed. Follow the MCP setup guide below. SDK and CLI npm registry publication is pending.

  • REST API

    Choose JavaScript, Python, Go, Java, C#, PHP or curl examples for the hosted API.

  • Client installation

    Install the reviewed private SDK and CLI release archives.

  • Command line

    Use the InboxSpec CLI in a terminal or test runner.

  • TypeScript SDK

    Register an inbox and wait for email from Node.js or Bun.

  • MCP

    Use Connect agent in your project to set up Claude Code, Codex or another MCP client with a project key.

  • Waiting for email

    Distinguish a match, a timeout and an error within one test deadline.

  • API reference

    Find request schemas, management operations and the OpenAPI document.

CI tests and diagnostics

  • CI email tests

    Connect setup, application delivery, assertions and scoped cleanup.

  • Troubleshooting

    Diagnose API configuration, environment and permission errors.

  • Fixtures

    Provision repeatable test inboxes and detect configuration drift.

  • OTP and link assertions

    Correlate verification codes and reset links with the exact application journey.

  • Limits and credentials

    Understand project access, quotas, key lifetimes and replacement.

  • GitHub and Vercel

    Use trusted workload identity for short-lived project access.

  • Service health

    Interpret fixture diagnostics and regional mail delivery observations.

Full API reference · OpenAPI schema · Error reference