OTP Inbox

Receive emails, extract OTP codes, retrieve them via API.

How It Works

  1. Send or forward an email containing an OTP to any address at this domain.
  2. The mail server receives it and passes it to Action Mailbox.
  3. OTP codes are automatically extracted and stored.
  4. Retrieve the code in your browser (HTML) or as JSON using the recipient email address, or stream the next one in real time.

Live Demo

Open a live stream and watch the next OTP arrive in real time. Enter a username (the part before @otpinbox.dev), start listening, then send a test email containing a code to that address.

Idle.

Endpoints

Each endpoint returns an HTML page by default. Append a .json extension to the path to get a JSON response instead.

GET /otp/john

Returns the most recent OTP for john@otpinbox.dev. Use /otp/john.json for JSON:

{
  "email": "john@otpinbox.dev",
  "otp_code": "482913",
  "subject": "Your verification code",
  "sender": "noreply@service.com",
  "received_at": "2026-07-01T12:00:00Z"
}
GET /otp/john?after=2026-07-01T12:00:00Z

Returns the most recent OTP received strictly after the given after timestamp (ISO 8601). Useful for polling for a new code after triggering a send.

GET /otp/john/all

Returns the 10 most recent OTPs for john@otpinbox.dev. Use /otp/john/all.json for JSON.

GET /otp/john/stream

Opens a Server-Sent Events stream that stays open and pushes the next OTP for john@otpinbox.dev the moment it arrives, then closes. Delivery is push-based — no polling. The event is named otp and its id is the OTP record id:

event: otp
id: 42
data: {"email":"john@otpinbox.dev","otp_code":"482913","subject":"Your verification code","sender":"noreply@service.com","received_at":"2026-07-01T12:00:00Z"}

After an OTP is delivered the server closes the stream. A browser's EventSource reconnects automatically with the Last-Event-ID header, which the server answers with 204 No Content to stop further reconnects. A fresh connection waits for the next OTP; if none arrives within 5 minutes it closes and the client reconnects to keep waiting.

const source = new EventSource("/otp/john/stream");
source.addEventListener("otp", (event) => {
  const otp = JSON.parse(event.data);
  console.log("Code:", otp.otp_code);
  source.close();
});

Error Responses

400 — Invalid after timestamp.

404 — No OTP found for that user.