@opensurf/inbox
A minimal, zero-dependency, open-source OTP inbox for OpenSurf.
It receives forwarded email, extracts a numeric one-time password, stores it for ~60 seconds, and exposes a read-once HTTP API.
About OpenSurf
OpenSurf builds infrastructure for reliable, user-controlled web agents. We believe that capbility, reliability and privacy are essential attributes of automated systems.
Find out more at https://opensurf.ai
Official service
If you just want to use it, the hosted service lives at https://opensurf.io/inbox/create
The source for that service live here https://github.com/opensurfai/inbox
Why this is secure (short answer)
This system is intentionally small and treats OTPs as short-lived, opaque secrets. Security relies on three guarantees:
-
Unforgeable routing
Inbox addresses embed an HMAC signature. WithoutEMAIL_INBOX_SECRET, attackers cannot guess or mint valid inbox keys. -
Unforgeable reads
Reads require a separate HMAC-derived API key. Knowing the inbox address does not grant read access. -
Short retention + read-once
OTPs expire quickly (~60s) and are deleted after the first successful read.
This keeps the blast radius small: no long-term storage, no mailbox history, and no recovery path for missed or leaked codes.
Self-hosting
The inbox is designed to run on Cloudflare Workers + Durable Objects via
alchemy.
Requirements
- Cloudflare account + domain
- Email Routing enabled for the domain
alchemyconfigured to deploy to Cloudflare
Configure
Create .env in lib/inbox:
ALCHEMY_PASSWORD='...'
EMAIL_INBOX_SECRET='...'
EMAIL_INBOX_DOMAIN='your-domain.example'
EMAIL_INBOX_SECRET should be a strong, private secret (distinct from
ALCHEMY_PASSWORD).
Run locally
bun run dev
Deploy
bun run deploy
After deployment, your API will be available at your domain, and emails routed
to <inboxKey>@your-domain.example.
API quickstart
- Create inbox:
GET /inbox/create
- Fetch OTP:
GET /inbox/<inboxKey>/otp?sender=example.com
Authorization: Bearer <apiKey>
Responses are JSON strings (the code) or null if none are available.