API Documentation

Overview

OTPBox provides a simple REST API for creating disposable email inboxes and retrieving verification codes programmatically.

All API responses are JSON. Rate limits apply: 10 requests per hour per IP.

Create Inbox

POST /api/inbox

Creates a new temporary inbox. Returns the inbox email address and access token.

Response
{
  "id": "abc123xyz789",
  "email": "abc123xyz789@box.otpbox.app",
  "expiresAt": 1704153600000,
  "token": "def456uvw012..."
}
Example
curl -X POST https://otpbox.app/api/inbox

Get Inbox State

GET /api/inbox/:token

Retrieves the inbox metadata and all messages. Messages are sorted newest first.

Response
{
  "inbox": {
    "id": "abc123xyz789",
    "email": "abc123xyz789@box.otpbox.app",
    "token": "def456uvw012...",
    "createdAt": 1704150000000,
    "expiresAt": 1704153600000
  },
  "messages": [
    {
      "id": "msg001",
      "inboxId": "abc123xyz789",
      "from": "noreply@service.com",
      "subject": "Your verification code",
      "body": "Your code is: 123456",
      "otp": "123456",
      "magicLink": null,
      "receivedAt": 1704150100000
    }
  ]
}

Get Latest Extraction

GET /api/inbox/:token/latest

Returns only the extracted OTP and/or magic link from the most recent message. Useful for CI/CD automation.

Response (200 OK)
{
  "otp": "123456",
  "link": "https://service.com/verify?token=...",
  "from": "noreply@service.com",
  "subject": "Your verification code",
  "receivedAt": 1704150100000
}
Response (404 Not Found)
{
  "error": "No messages found"
}

This endpoint returns 404 when the inbox exists but has no messages yet. Use a wait/retry loop in your automation (see CI examples below).

CI / Automation

OTPBox is designed for headless automation. Create a disposable inbox, trigger your app to send a verification email, then poll for the OTP.

Shell Script Example

#!/bin/bash
set -e

# 1. Create disposable inbox
echo "Creating inbox..."
RESPONSE=$(curl -s -X POST https://otpbox.app/api/inbox)
TOKEN=$(echo "$RESPONSE" | jq -r '.token')
EMAIL=$(echo "$RESPONSE" | jq -r '.email')

echo "Inbox: $EMAIL"
echo "Token: $TOKEN"

# 2. Trigger your app to send verification email to $EMAIL
# Example: curl -X POST https://yourapp.com/signup -d "email=$EMAIL"
echo "Triggering verification email..."
# ... your app logic here ...

# 3. Poll for OTP (wait up to 30 seconds)
echo "Waiting for OTP..."
MAX_ATTEMPTS=10
SLEEP_SECONDS=3

for i in $(seq 1 $MAX_ATTEMPTS); do
  RESPONSE=$(curl -s https://otpbox.app/api/inbox/$TOKEN/latest)
  OTP=$(echo "$RESPONSE" | jq -r '.otp // empty')
  
  if [ -n "$OTP" ] && [ "$OTP" != "null" ]; then
    echo "✓ Got OTP: $OTP"
    
    # 4. Use the OTP in your test
    # Example: curl -X POST https://yourapp.com/verify -d "code=$OTP"
    exit 0
  fi
  
  echo "  Attempt $i/$MAX_ATTEMPTS - no message yet, waiting..."
  sleep $SLEEP_SECONDS
done

echo "✗ Timeout: No OTP received after $MAX_ATTEMPTS attempts"
exit 1

GitHub Actions Example

name: E2E Verification Test

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Create OTPBox inbox
        id: inbox
        run: |
          RESPONSE=$(curl -s -X POST https://otpbox.app/api/inbox)
          echo "token=$(echo $RESPONSE | jq -r '.token')" >> $GITHUB_OUTPUT
          echo "email=$(echo $RESPONSE | jq -r '.email')" >> $GITHUB_OUTPUT
      
      - name: Trigger signup with OTPBox email
        run: |
          curl -X POST https://yourapp.com/api/signup \
            -H "Content-Type: application/json" \
            -d '{"email": "${{ steps.inbox.outputs.email }}"}'
      
      - name: Wait for OTP
        id: otp
        run: |
          for i in {1..10}; do
            RESPONSE=$(curl -s https://otpbox.app/api/inbox/${{ steps.inbox.outputs.token }}/latest)
            OTP=$(echo "$RESPONSE" | jq -r '.otp // empty')
            
            if [ -n "$OTP" ] && [ "$OTP" != "null" ]; then
              echo "otp=$OTP" >> $GITHUB_OUTPUT
              echo "✓ Received OTP: $OTP"
              exit 0
            fi
            
            echo "Waiting for OTP (attempt $i/10)..."
            sleep 3
          done
          
          echo "✗ Timeout waiting for OTP"
          exit 1
      
      - name: Verify OTP
        run: |
          curl -X POST https://yourapp.com/api/verify \
            -H "Content-Type: application/json" \
            -d '{"code": "${{ steps.otp.outputs.otp }}"}'

Rate Limits & Best Practices

Rate Limit:10 requests per hour per IP address
Inbox Lifetime:1 hour from creation
Polling Strategy:Poll every 3-5 seconds, max 10-15 attempts
Error Handling:/latest returns 404 when inbox is empty. Check response.otp for null or empty.
Free Tier:All features available. Rate limits prevent abuse.

Wait/Retry Pattern

Email delivery typically takes 1-5 seconds. The /latest endpoint returns 404 with { "error": "No messages found" } when the inbox exists but has no messages yet.

Recommended pattern: Poll every 3 seconds for up to 30 seconds (10 attempts). This handles normal email latency while staying well under rate limits.

# Minimal wait/retry in curl
for i in {1..10}; do
  OTP=$(curl -s https://otpbox.app/api/inbox/$TOKEN/latest | jq -r '.otp // empty')
  [ -n "$OTP" ] && [ "$OTP" != "null" ] && break
  sleep 3
done

Error Responses

404 Not Found

Inbox does not exist

410 Gone

Inbox has expired

429 Too Many Requests

Rate limit exceeded

Notes

  • Inboxes expire automatically after 1 hour
  • Tokens are opaque and random - do not parse or predict them
  • Messages appear typically within seconds of being sent
  • For real-time updates, poll every 3-5 seconds or use the web UI
  • OTP extraction uses regex patterns for 4-8 digit codes
  • Magic link detection looks for common verification URL patterns