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
Copy test addressOpen your project’s Inboxes page and choose Copy test address.
- 2
Send an emailUse your app or email client. Include “Your code is 123456” in the message.
- 3
Find the codeThe inbox appears when mail arrives. Open it to read the full message and copy the code.
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.