Python SDK
Test, debug, and automate signup, OTP, and email-based authentication flows — with real-time observability.
Why this exists
Testing auth flows is painful:
- ❌ Flaky email delivery
- ❌ Polling delays
- ❌ OTP parsing issues
- ❌ No visibility into failures
FreeCustom.Email solves this by giving you: 👉 real-time auth flow debugging.
📦 Installation
bash
pip install freecustom-email🚀 Quick Start (Auth Flow Testing)
python
import asyncio
from freecustom_email import FreeCustomEmail
async def main():
client = FreeCustomEmail(api_key="fce_your_api_key_here")
email = "test@ditube.info"
# 1. Create inbox (pass `is_testing=True` for zero-latency testing mode)
await client.inboxes.register(email, is_testing=True)
# 2. Start test run (NEW - Groups events in your timeline)
await client.inboxes.start_test(email, "signup-test-1")
# 3. Trigger your app (e.g. using httpx or playwright)
# await httpx.post("https://yourapp.com/api/send-otp", json={"email": email})
# 4. Wait for OTP
otp = await client.otp.wait_for(email)
print(f"OTP: {otp}")
# 5. Debug the full flow
timeline = await client.inboxes.get_timeline(email, "signup-test-1")
print(timeline)
if __name__ == "__main__":
asyncio.run(main())🔥 Debug Your Auth Flow
Timeline (see what actually happened)
python
timeline = await client.inboxes.get_timeline(email)
for event in timeline.events:
print(f"[{event.type}] - {event.time}ms")Insights (why your test failed)
python
insights = await client.inboxes.get_insights(email)
for insight in insights:
print(f"[{insight.type}] {insight.message}")Test Runs (group your flows)
python
await client.inboxes.start_test(email, "signup-test-1")
timeline = await client.inboxes.get_timeline(email, "signup-test-1")⚡ Real-time Debugging (WebSocket)
python
ws = client.realtime(mailbox=email)
@ws.on("email")
async def on_email(event):
print(f"Flow update: {event}")
await ws.connect()
await ws.wait()⚙️ Synchronous Mode (Selenium / Pytest)
python
from freecustom_email import FreeCustomEmail
client = FreeCustomEmail(api_key="fce_...", sync=True)
# 1. Register
client.inboxes.register("test@ditube.info", is_testing=True)
# 2. Wait
otp = client.otp.wait_for("test@ditube.info")
print("OTP:", otp)🔁 Old vs New Mental Model
| Old (Temp Mail) | New (FreeCustom.Email) |
|---|---|
| receive emails | test auth flows |
| read inbox | debug flows |
| parse OTP manually | auto extract + analyze |
| polling | real-time events |
🔥 Most Important Methods (for devs)
client.inboxes.start_test(email, test_id)client.otp.wait_for(email)client.inboxes.get_timeline(email, test_id)client.inboxes.get_insights(email)
📚 Full API Reference
Client
python
from freecustom_email import FreeCustomEmail
# Async client
client = FreeCustomEmail(
api_key="fce_...", # required
base_url="https://...", # optional
timeout=10, # optional, seconds
)
# Sync client
sync_client = FreeCustomEmail(api_key="fce_...", sync=True)Inboxes
python
# Register
await client.inboxes.register("mytest@ditube.info")
# List all registered inboxes
inboxes = await client.inboxes.list()
# Unregister
await client.inboxes.unregister("mytest@ditube.info")Messages
python
# List all messages
messages = await client.messages.list("mytest@ditube.info")
# Get a specific message
msg = await client.messages.get("mytest@ditube.info", "D3vt8NnEQ")
print(msg.subject, msg.otp)
# Delete a message
await client.messages.delete("mytest@ditube.info", "D3vt8NnEQ")
# Wait for a message
msg = await client.messages.wait_for("mytest@ditube.info", timeout=30)OTP
python
# Get latest OTP
result = await client.otp.get("mytest@ditube.info")
if result.otp:
print(f"OTP: {result.otp}")
# Wait for OTP
otp = await client.otp.wait_for("mytest@ditube.info", timeout=30)
print(f"Got OTP: {otp}")Real-time WebSocket
python
ws = client.realtime(
mailbox="mytest@ditube.info",
auto_reconnect=True
)
@ws.on("connected")
async def on_connected(info):
print("Connected")
@ws.on("email")
async def on_email(email):
print(f"New email OTP: {email.otp}")
await ws.connect()
await ws.wait()Domains
python
# List available domains
domains = await client.domains.list()
# Custom domains
custom = await client.domains.list_custom()
result = await client.domains.add_custom("mail.yourdomain.com")
verification = await client.domains.verify_custom("mail.yourdomain.com")
await client.domains.remove_custom("mail.yourdomain.com")Webhooks
python
# Register a webhook
hook = await client.webhooks.register(
"mytest@ditube.info",
"https://your-server.com/hooks/email"
)
# List active webhooks
hooks = await client.webhooks.list()
# Unregister
await client.webhooks.unregister(hook.id)Account
python
# Account info
info = await client.account.info()
# Usage stats
usage = await client.account.usage()Error Handling
python
from freecustom_email import (
AuthError,
PlanError,
RateLimitError,
NotFoundError,
TimeoutError
)
try:
otp = await client.otp.get("mytest@ditube.info")
except AuthError:
print("Invalid API key")
except PlanError as e:
print(f"Plan too low: {e}")Links
- pypi.org/project/freecustom-email — PyPI package page
- Interactive Playground — try API calls in the browser