📱 OpenInbox is now on Android & iOS! Get the app today.

OpenInbox on Telegram

Get a temp inbox right inside Telegram.

Open Telegram bot

Custom domains

Use your own domain on paid plans.

Learn More
Developer API • /nodejs

/nodejs Temp Email API

Create disposable inboxes, receive verification emails, and extract OTP codes from Node.js — a tiny helper built on native fetch (Node 18+) plus a runnable test with the built-in test runner.

Email-dependent tests — signup confirmation, OTP login, password reset — are awkward in Node because the verification email lands in a mailbox your test can't read. The OpenInbox API gives each test its own disposable inbox over plain HTTP: create it, trigger your flow, poll, and pull the code out of the body. The examples below use Node's built-in fetch and test runner, so there are no dependencies to install, and they run against the real API.

How the flow works

  • Create a disposable inbox: POST /api/inbox (no auth) → { id, email, expiresAt }.
  • Use that address in your signup/login request so your app emails it.
  • Poll GET /api/inbound/api/emails?inboxEmail=<email> with the X-API-KEY header until an email arrives.
  • Match a 4–8 digit code (or URL) in the email textBody with a regex.
  • Submit the code / visit the link and assert.

Setup

Node 18+ ships with a global fetch and a built-in test runner, so nothing to install for the basics. Reading the inbox is a premium endpoint, so put your key in an environment variable.

terminalbash
# Node 18+ has global fetch and a built-in test runner.
node --version   # v18 or newer

export OPENINBOX_API_KEY="your-premium-api-key"

A small OpenInbox helper

Keep the API out of your tests with a two-function module. createInbox creates a fresh inbox; waitForOtp polls the inbox and returns the first 4–8 digit code it finds in textBody.

openinbox.mjsjavascript
const BASE = 'https://api.openinbox.io/api';
const API_KEY = process.env.OPENINBOX_API_KEY;

export async function createInbox() {
  // Creating an inbox needs no auth
  const res = await fetch(`${BASE}/inbox`, { method: 'POST' });
  return res.json(); // { id, email, expiresAt, ... }
}

export async function waitForOtp(inboxEmail, timeoutMs = 30_000) {
  const deadline = Date.now() + timeoutMs;
  while (Date.now() < deadline) {
    const res = await fetch(
      `${BASE}/inbound/api/emails?inboxEmail=${encodeURIComponent(inboxEmail)}`,
      { headers: { 'X-API-KEY': API_KEY } },
    );
    const { emails } = await res.json();
    if (emails.length > 0) {
      const otp = emails[0].textBody?.match(/\b\d{4,8}\b/)?.[0];
      if (otp) return otp;
    }
    await new Promise((r) => setTimeout(r, 2_000));
  }
  throw new Error('No OTP email arrived in time');
}

A test with the built-in runner

Run this with node --test — no Jest or Vitest required. Create an inbox, trigger your signup, wait for the code, and assert. The same helper works unchanged in Jest, Vitest, or a Playwright test.

signup.test.mjsjavascript
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { createInbox, waitForOtp } from './openinbox.mjs';

test('signup sends a verification code', async () => {
  const inbox = await createInbox();

  // Trigger your app so it emails the verification code
  await fetch('https://staging.yourapp.com/api/register', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email: inbox.email, password: 'Str0ng!Pass' }),
  });

  const otp = await waitForOtp(inbox.email);
  assert.match(otp, /^\d{4,8}$/);

  // …submit otp to your verify endpoint and assert the success state
});

Jest, Vitest, and Playwright

The helper is plain fetch, so it drops into any runner. In Jest or Vitest, raise the timeout (jest.setTimeout(60_000) / test(..., { timeout: 60_000 })) because you are hitting real networks. In Playwright, you can use the same module or the built-in request fixture to create the inbox before driving the browser.

Common pitfalls

  • Bound the polling loop with a deadline (as shown) — an unbounded loop will hang your test run if the email never arrives.
  • Raise your test framework timeout. The default (often 5s) is shorter than the email + polling window; allow ~60s.
  • Creating an inbox needs no auth, but GET /api/inbound/api/emails is premium. A 401/403 means the X-API-KEY env var is missing or the plan is not paid.
  • Read emails[0].textBody — there is no pre-parsed code field. The /\b\d{4,8}\b/ regex grabs any 4–8 digit run; narrow it if the body has other numbers.
  • On Node 16 or older there is no global fetch — either upgrade to Node 18+ or import node-fetch.

Frequently Asked Questions

How do I create a temporary email in Node.js?

Call fetch on POST https://api.openinbox.io/api/inbox (no auth) and read the email field from the JSON response, which also includes id and expiresAt. Node 18+ has fetch built in.

Do I need an API key?

Creating an inbox is unauthenticated. Polling received emails (GET /api/inbound/api/emails) requires a premium X-API-KEY, read from the OPENINBOX_API_KEY environment variable.

How do I extract the OTP code in JavaScript?

Run emails[0].textBody.match(/\b\d{4,8}\b/)?.[0] on the email returned by the poll endpoint. There is no separate parsed field — it is a one-line regex on textBody.

Does this work with Jest, Vitest, or Playwright?

Yes — the helper is plain fetch, so it works in any runner. Increase the test timeout to ~60s, and in Playwright you can also use the request fixture to create the inbox.

Which Node version do I need?

Node 18+ for the global fetch and built-in test runner. On older versions, import node-fetch and use Jest/Vitest instead.

How long does a disposable inbox last?

Free inboxes expire after one hour, ample for a test. Create a fresh inbox per test so parallel tests stay isolated.

Related Pages

Explore More

Your private inbox is one click away

Free, instant, no registration needed. Works with any service. Expires automatically after 1 hour.

View API Docs