DEVELOPER DOCUMENTATION REST API · v1

Build email into
your workflow.

Create an inbox, receive messages, and stream verification codes. A straightforward API for your next integration.

Before your first request
  1. 01
    Activate Developer

    API access is included with the Developer website plan.

  2. 02
    Create an account API key

    Manage your keys and scopes in account settings.

  3. 03
    Authenticate every request

    Send your key in the authorization header.

Authorization: Bearer YOUR_API_KEY

Create first, then send. Only mail received while an inbox is active is stored. Other mail to a valid receiving domain is accepted and discarded.

QUICK START

Your first inbox

One request creates an address, ready to receive mail.

usernameoptional
Choose a name, or omit it for a random address.
domain_idoptional
Choose from GET /v1/domains, or let us select one: custom first, then premium, then free.

Premium and custom inboxes are private. Free-domain inboxes are shared and public.

Random addresses & inbox limits

Random names use 3–5 alternating consonant/vowel letters plus 3–5 digits, such as bav472 or tavid20485. Developer allows up to 50 total inboxes.

Terminal · cURL
curl --request POST \
  "$TMB_API_ORIGIN/v1/inboxes" \
  --header "Authorization: Bearer $TMB_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"username":"your-name"}'
Set TMB_API_ORIGIN to your API origin (locally http://localhost:3000) and TMB_API_KEY to your account API key.
REST API

Endpoint reference

View OpenAPI

Create and manage inboxes, read messages, and subscribe to incoming mail.

Download the original email with GET /v1/inboxes/:id/messages/:messageId/source. It returns an .eml file with the original headers, MIME bodies and attachments. Message details include source_download_url. Downloads share the attachment rate limit and normal message expiration.

To star a message, send PATCH /v1/inboxes/:id/messages/:messageId/star with starred set to true (or false). Lists and message details include your personal starred status. Stars expire with the message.

EndpointPurpose
GET /v1/domainsActive domains and expiry warnings
POST /v1/inboxesCreate an inbox on an eligible domain
DELETE /v1/inboxes/:idDelete an inbox, its messages and attachments
DELETE /v1/inboxes/:id/messages/:messageIdDelete a message and its attachments
GET /v1/inboxes/:id/messagesPaginated received mail
GET /v1/inboxes/:id/messages/:messageIdPlain text, sanitized HTML, attachment metadata
GET /v1/inboxes/:id/messages/:messageId/attachments/:attachmentIdDownload the original attachment bytes
GET /v1/inboxes/:id/eventsServer-sent events with resumable cursor
GET /v1/inboxes/:id/otp/eventsDeveloper-only OTP stream for an owned private inbox; closes after 60 seconds
POST /v1/abuse-reportsReport unsafe content
VERIFICATION CODES

Stream new OTP codes

Watch an inbox for verification codes as mail arrives. One request opens a 60-second window.

GET/v1/inboxes/:id/otp/events
Access
Developer API key · messages:read
Inbox
Your private website inbox
Window
New mail only · up to 60 seconds

1. Start watching

Run this request with your API key and inbox ID.

Terminal · cURL
curl --no-buffer --max-time 70 \
  -H "Authorization: Bearer $TMB_API_KEY" \
  -H "Accept: text/event-stream" \
  "$TMB_API_ORIGIN/v1/inboxes/$INBOX_ID/otp/events"

Set TMB_API_ORIGIN to your API origin (locally, http://localhost:3000) and INBOX_ID to the inbox UUID. --no-buffer displays events immediately.

2. Handle incoming events

The response streams Server-Sent Events as they happen.

Decoded JSON · otp.found
{
  "inbox_id": "INBOX_ID",
  "message_id": "MESSAGE_ID",
  "sender": "[email protected]",
  "subject": "Your verification code",
  "received_at": "2026-10-14T12:00:01.000Z",
  "expires_at": "2026-11-13T12:00:01.000Z",
  "code": "001234",
  "source": "text",
  "confidence": "high",
  "confidence_score": 95,
  "signals": [
    "explicit_otp_label",
    "numeric_code"
  ],
  "reliability": {
    "method": "heuristic",
    "verified": false
  }
}

otp.found includes the candidate code, message metadata, and confidence signals. Codes remain strings to preserve leading zeroes.

New arrivals, automatically bounded

Existing messages are excluded. The connection stays open after a match and closes after 60 seconds, even if no codes arrive. Each connection uses one API request.

Confidence is a hint

Scores come from extraction rules, not verified accuracy. The service does not authenticate the sender or check a code with its issuer.

Connection behavior and access requirements

Use a Developer account API key with messages:read. The inbox must belong to that key’s account. Public inboxes, RevenueCat mobile inboxes, and website session cookies do not authorize this endpoint.

The response uses text/event-stream. Older deliveries are excluded even if parsed after connection; new mail must finish parsing before the stream closes. Heartbeat comments keep the connection active while waiting.

Start a new request for another window. Query parameters and Last-Event-ID replay are not supported. The cURL client timeout of 70 seconds allows time for the server’s 60-second window.

A stream.error event means access or service failure interrupted the stream; start a new request after resolving the cause.

Fields, extraction limits, and HTTP errors

code is a string, preserving leading zeroes. Each candidate includes inbox_id, message_id, sender, subject, received_at, and expires_at. The timestamps describe the message’s server receipt and retention deadline; they do not establish when the OTP itself expires. Sender and subject metadata are limited to 1,024 characters each.

confidence is high for an explicit nearby OTP label or medium for a generic code/PIN label or an OTP subject with a code near the start of the body. confidence_score is an uncalibrated rule score, not a probability or percentage accuracy. signals explains the match, and source identifies subject, text, or html. The service does not verify the sender or validate the code with its issuer; reliability.verified is always false.

Extraction supports labelled 4–8 digit codes, including grouped six-digit codes, and mixed uppercase-letter/digit codes of 6–10 characters. It scans the subject and the first 128 KiB of plain text, with a fallback for HTML-only messages. Attachments are not scanned. Codes repeated within one message are deduplicated, with at most 16 candidates per message. False positives and missed codes are possible.

Each connection consumes one API request; streamed candidates do not consume extra requests. Concurrency is limited across the account’s keys. Cancellation, revoked access, inbox deletion, service failure, or a slow consumer can end the stream early. A complete event with reason: timeout is normal, including when codes_found is zero.

Before streaming starts, HTTP 401 indicates a missing, invalid, or revoked key; HTTP 403 indicates a missing scope or unavailable plan feature; HTTP 404 means the inbox is unavailable or not owned by the account. HTTP 422 rejects invalid parameters or a replay cursor, and HTTP 429 indicates a request or stream limit.

Full example in SSE wire format

Each event has an event: line and a single-line JSON data: value, separated from the next event by a blank line. The panel above formats the decoded JSON for readability.

text/event-stream
event: ready
data: {"inbox_id":"INBOX_ID","started_at":"2026-10-14T12:00:00.000Z","deadline":"2026-10-14T12:01:00.000Z","extraction_version":"otp-heuristic-v1"}

event: otp.found
data: {"inbox_id":"INBOX_ID","message_id":"MESSAGE_ID","sender":"[email protected]","subject":"Your verification code","received_at":"2026-10-14T12:00:01.000Z","expires_at":"2026-11-13T12:00:01.000Z","code":"001234","source":"text","confidence":"high","confidence_score":95,"signals":["explicit_otp_label","numeric_code"],"reliability":{"method":"heuristic","verified":false}}

event: complete
data: {"reason":"timeout","codes_found":1,"finished_at":"2026-10-14T12:01:00.000Z"}
FILES & ATTACHMENTS

Download an attachment

Get the attachment URL, then download the original bytes.

  1. 1

    Read the message

    Open its details and find the attachments array. Each entry includes an ID, filename, size, content type, and download_url.

  2. 2

    Save the attachment

    Append the relative download_url to your API origin. Save the response directly to a file.

Your key, your inbox

Use a Developer account key with messages:read. Private attachments also require inbox ownership.

Public downloads on the website use the browser session.

Terminal · cURL
curl --fail \
  -H "Authorization: Bearer $TMB_API_KEY" \
  "$TMB_API_ORIGIN$DOWNLOAD_URL" \
  --output attachment.bin
DOWNLOAD_URL is the relative URL from the attachment. Use the same TMB_API_ORIGIN and TMB_API_KEY as the quick start.
200 OK Binary response
Content-Type
application/octet-stream
Content-Disposition
Original filename
30 downloads / minute / clientShared with raw email downloads404 if deleted, expired, or missing
SERVICE BEHAVIOR

Limits & retention

The limits and lifetimes to build around.

MESSAGE RETENTION

Up to 30 days

Developer messages expire from the moment they arrive. Reading a message never resets its clock.

Plan changes affect future deliveries. Existing deadlines stay fixed.
RECEIVING ACCESS

A separate clock

Public inbox activity and retention follow the creator’s plan. Private addresses receive while their owner’s paid entitlement is active.

API requests require an account-owned key and an active Developer plan.
PAGINATION

50 items per page

Use the returned next_cursor to fetch the next page. Keep going until the cursor is empty.

Fetch only what you need and keep the cursor unchanged between requests.

Handle the response

429
Slow down

Respect Retry-After before trying again.

503
Service unavailable

A required service is unavailable. Retry with backoff.