Skip to content

Getting Started

The MinuteMail Python SDK provides a simple interface to interact with the MinuteMail API with 100% API coverage.

Source code: github.com/minutemailco/minutemail-python

Install from PyPI:

Terminal window
pip install minutemail-sdk

For development:

Terminal window
git clone https://github.com/minutemailco/minutemail-python
cd minutemail-python
pip install -e .
  • Python 3.9+
  • requests >= 2.31.0
from minutemail import MinuteMailClient, APIError
# Initialize the client
client = MinuteMailClient(api_key="mmak_YOUR_API_KEY")
try:
# Create a temporary mailbox (note: expires_in is an integer in minutes)
mailbox = client.create_mailbox(
domain="minutemail.cc",
expires_in=30, # 30 minutes (integer, not string!)
recoverable=True,
tag="onboarding-flow"
)
print(f"Mailbox created: {mailbox['address']}")
print(f"Expires at: {mailbox['expiresAt']}")
# Wait for emails (in production, use polling)
# ...
# List received emails
mails = client.list_mails(mailbox["id"])
for mail in mails["items"]:
print(f"From: {mail['sender']}")
print(f"Subject: {mail['subject']}")
# Clean up
client.delete_mailbox(mailbox["id"])
except APIError as e:
print(f"API Error: {e.message} (status: {e.status_code})")

The SDK requires an API key for all authenticated operations.

from minutemail import MinuteMailClient
client = MinuteMailClient(api_key="mmak_YOUR_API_KEY")
ParameterTypeRequiredDefaultDescription
api_keystr-Your MinuteMail API key
base_urlstrhttps://api.minutemail.coAPI base URL (no /v1 suffix)
timeoutfloat10.0Request timeout in seconds
sessionrequests.SessionNoneCustom session for connection pooling

Store your API key securely using environment variables:

import os
from minutemail import MinuteMailClient
client = MinuteMailClient(
api_key=os.getenv("MINUTEMAIL_API_KEY"),
base_url=os.getenv("MINUTEMAIL_BASE_URL", "https://api.minutemail.co")
)

For self-hosted instances or local development:

client = MinuteMailClient(
api_key="your-api-key",
base_url="http://localhost:8080" # Local development
)
client = MinuteMailClient(
api_key="your-api-key",
base_url="https://api.your-domain.com" # Self-hosted
)

Adjust timeout for slow networks or long-running operations:

client = MinuteMailClient(
api_key="your-api-key",
timeout=30.0 # 30 seconds
)
  1. Log in to your MinuteMail dashboard at MinuteMail
  2. Click your profile menuAPI Keys
  3. Click Create API Key
  4. (Optional) Configure Domain Restrictions to limit where the key can be used
  5. Copy and securely store your key

Security Note: Never commit API keys to version control. Use environment variables or secret management tools.

For enhanced security, you can configure domain restrictions when creating an API key. This limits which domains can use the key - useful when deploying to client-side applications.

Supported formats:

  • example.com - Exact domain match
  • *.example.com - Wildcard for subdomains
  • localhost:3000 - Development domains with ports

If your SDK requests receive 403 Forbidden errors mentioning domain restrictions, verify that:

  1. Your API key has the correct domains configured in the dashboard
  2. Your application is running on an allowed domain
  3. Your requests include proper Origin, Referer, or Host headers

The SDK raises specific exceptions for different error conditions.

Raised when the API returns a non-2xx status code.

from minutemail import MinuteMailClient, APIError
client = MinuteMailClient(api_key="your-api-key")
try:
mailbox = client.create_mailbox(domain="invalid-domain")
except APIError as e:
print(f"Status: {e.status_code}")
print(f"Error: {e.error}")
print(f"Message: {e.message}")

Attributes:

  • status_code (int): HTTP status code
  • error (str): Error code from API
  • message (str): Human-readable error message

Raised for network-related failures (timeouts, connection errors).

from minutemail import TransportError
try:
mailbox = client.create_mailbox(domain="minutemail.cc")
except TransportError as e:
print(f"Network error: {e}")
# Implement retry logic

Base exception class for SDK-specific errors (e.g., validation).

from minutemail import MinuteMailError
try:
mailbox = client.create_mailbox(
domain="minutemail.cc",
recoverable=True,
tag="" # Empty tag with recoverable=True
)
except MinuteMailError as e:
print(f"Validation error: {e}")

from minutemail import APIError
try:
client = MinuteMailClient(api_key="invalid-key")
mailbox = client.create_mailbox(domain="minutemail.cc")
except APIError as e:
if e.status_code == 401:
print("Invalid API key. Please check your credentials.")
try:
mailbox = client.create_mailbox(domain="minutemail.cc")
except APIError as e:
if e.status_code == 429 and e.error == "quota_exceeded":
print(f"Quota exceeded: {e.message}")
print("Please upgrade your plan or wait for quota reset.")
try:
mailbox = client.get_mailbox("non-existent-id")
except APIError as e:
if e.status_code == 404:
print("Mailbox not found. It may have expired.")
try:
mailbox = client.create_mailbox(domain="minutemail.cc")
except APIError as e:
if e.status_code == 403 and "domain" in e.message.lower():
print("API key not authorized for this domain.")
print("Check domain restrictions in your dashboard.")
from minutemail import TransportError
try:
mailbox = client.create_mailbox(domain="minutemail.cc")
except TransportError as e:
print(f"Network error: {e}")
print("Check your internet connection or increase timeout.")

from minutemail import MinuteMailClient, APIError, TransportError, MinuteMailError
client = MinuteMailClient(api_key="your-api-key")
def create_mailbox_safe(domain, **kwargs):
"""
Create a mailbox with comprehensive error handling.
"""
try:
mailbox = client.create_mailbox(domain=domain, **kwargs)
return mailbox
except MinuteMailError as e:
# SDK validation errors
print(f"Validation error: {e}")
return None
except APIError as e:
# API-level errors
if e.status_code == 401:
print("Authentication failed. Check your API key.")
elif e.status_code == 429:
print(f"Rate limit or quota exceeded: {e.message}")
elif e.status_code == 409:
print(f"Conflict: {e.message}")
else:
print(f"API error [{e.status_code}]: {e.message}")
return None
except TransportError as e:
# Network errors
print(f"Network error: {e}")
print("Please check your internet connection.")
return None
except Exception as e:
# Unexpected errors
print(f"Unexpected error: {e}")
return None
# Usage
mailbox = create_mailbox_safe(
domain="minutemail.cc",
recoverable=True,
tag="test",
expires_in=30
)
if mailbox:
print(f"Success: {mailbox['address']}")
else:
print("Failed to create mailbox")
import time
from minutemail import APIError, TransportError
def create_mailbox_with_retry(domain, max_retries=3, **kwargs):
"""
Create mailbox with exponential backoff retry.
"""
for attempt in range(max_retries):
try:
return client.create_mailbox(domain=domain, **kwargs)
except (APIError, TransportError) as e:
if attempt == max_retries - 1:
# Last attempt, raise the exception
raise
# Calculate backoff time (exponential: 1s, 2s, 4s, ...)
backoff = 2 ** attempt
print(f"Attempt {attempt + 1} failed: {e}")
print(f"Retrying in {backoff} seconds...")
time.sleep(backoff)
# Usage
try:
mailbox = create_mailbox_with_retry(
domain="minutemail.cc",
expires_in=30
)
print(f"Created: {mailbox['address']}")
except Exception as e:
print(f"Failed after retries: {e}")
import logging
from minutemail import APIError, TransportError
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
def create_mailbox_with_logging(domain, **kwargs):
"""
Create mailbox with proper logging.
"""
try:
logger.info(f"Creating mailbox with domain: {domain}")
mailbox = client.create_mailbox(domain=domain, **kwargs)
logger.info(f"Mailbox created: {mailbox['address']}")
return mailbox
except APIError as e:
logger.error(
f"API error creating mailbox: {e.message}",
extra={
'status_code': e.status_code,
'error_code': e.error,
'domain': domain
}
)
raise
except TransportError as e:
logger.error(f"Network error creating mailbox: {e}")
raise
# Usage
try:
mailbox = create_mailbox_with_logging(
domain="minutemail.cc",
expires_in=30
)
except Exception:
logger.exception("Failed to create mailbox")

Status CodeError CodeDescriptionAction
400bad_requestInvalid request (malformed JSON, missing fields)Check request parameters
400invalid_durationInvalid duration formatUse formats like "30m", "2h"
401unauthorizedInvalid or missing API keyVerify API key
403forbiddenAccess denied or domain restriction failedCheck permissions and domain configuration
404not_foundResource not foundVerify resource ID
409conflictResource conflictCheck for duplicate resources
429rate_limit_exceededToo many requestsImplement backoff
429quota_exceededUsage quota exceededUpgrade plan or wait for reset
500internal_errorServer errorRetry or contact support
503service_unavailableService unavailableRetry after delay

Use a custom requests.Session for connection pooling and automatic retries.

from minutemail import MinuteMailClient
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
# Create session with retry strategy
session = requests.Session()
retry_strategy = Retry(
total=3, # Total retries
backoff_factor=0.3, # Wait 0.3s, 0.6s, 1.2s between retries
status_forcelist=[429, 500, 502, 503, 504], # Retry on these status codes
allowed_methods=["GET", "POST", "DELETE"] # Retry these methods
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("https://", adapter)
session.mount("http://", adapter)
# Create client with custom session
client = MinuteMailClient(
api_key="your-api-key",
timeout=30.0,
session=session
)
# Use client normally - retries happen automatically
mailbox = client.create_mailbox(domain="minutemail.cc")

Improve performance for multiple requests by reusing connections.

from minutemail import MinuteMailClient
import requests
# Create session with connection pooling
session = requests.Session()
adapter = requests.adapters.HTTPAdapter(
pool_connections=10,
pool_maxsize=20
)
session.mount("https://", adapter)
client = MinuteMailClient(
api_key="your-api-key",
session=session
)
# Multiple requests reuse the same connection
for i in range(10):
mailbox = client.create_mailbox(
domain="minutemail.cc",
tag=f"test-{i}",
expires_in=15 # 15 minutes
)
print(f"Created: {mailbox['address']}")

Load configuration from environment variables.

import os
from minutemail import MinuteMailClient
class MinuteMailConfig:
"""Configuration from environment variables."""
def __init__(self):
self.api_key = os.getenv("MINUTEMAIL_API_KEY")
self.base_url = os.getenv(
"MINUTEMAIL_BASE_URL",
"https://api.minutemail.co"
)
self.timeout = float(os.getenv("MINUTEMAIL_TIMEOUT", "10.0"))
if not self.api_key:
raise ValueError("MINUTEMAIL_API_KEY environment variable required")
def create_client(self):
return MinuteMailClient(
api_key=self.api_key,
base_url=self.base_url,
timeout=self.timeout
)
# Usage
config = MinuteMailConfig()
client = config.create_client()
mailbox = client.create_mailbox(domain="minutemail.cc")
print(f"Created: {mailbox['address']}")

Example .env file:

Terminal window
MINUTEMAIL_API_KEY=mmak_FKI5IKBJ4FSZJLUFGJ3IMF4A55W2OZW7YMLWD3JI33IVUGDEJXLQ
MINUTEMAIL_BASE_URL=https://api.minutemail.co
MINUTEMAIL_TIMEOUT=30.0

Wrap the synchronous SDK in async functions for integration with async code.

import asyncio
from concurrent.futures import ThreadPoolExecutor
from minutemail import MinuteMailClient
client = MinuteMailClient(api_key="your-api-key")
executor = ThreadPoolExecutor(max_workers=5)
async def create_mailbox_async(domain, **kwargs):
"""Async wrapper for create_mailbox."""
loop = asyncio.get_event_loop()
return await loop.run_in_executor(
executor,
lambda: client.create_mailbox(domain=domain, **kwargs)
)
async def list_mails_async(mailbox_id):
"""Async wrapper for list_mails."""
loop = asyncio.get_event_loop()
return await loop.run_in_executor(
executor,
lambda: client.list_mails(mailbox_id)
)
# Usage
async def main():
# Create mailboxes concurrently
mailboxes = await asyncio.gather(
create_mailbox_async("minutemail.cc", tag="test-1"),
create_mailbox_async("minutemail.cc", tag="test-2"),
create_mailbox_async("minutemail.cc", tag="test-3")
)
for mailbox in mailboxes:
print(f"Created: {mailbox['address']}")
# Check emails concurrently
results = await asyncio.gather(
*[list_mails_async(mb["id"]) for mb in mailboxes]
)
for i, mails in enumerate(results):
print(f"Mailbox {i+1}: {len(mails['items'])} emails")
asyncio.run(main())

Create a context manager for automatic mailbox cleanup.

from minutemail import MinuteMailClient
from contextlib import contextmanager
client = MinuteMailClient(api_key="your-api-key")
@contextmanager
def temporary_mailbox(domain, **kwargs):
"""
Context manager that creates a mailbox and automatically deletes it.
Usage:
with temporary_mailbox("minutemail.cc", expires_in=30) as mailbox:
# Use mailbox
print(mailbox['address'])
# Mailbox is automatically deleted here
"""
mailbox = client.create_mailbox(domain=domain, **kwargs)
try:
yield mailbox
finally:
try:
client.delete_mailbox(mailbox["id"])
print(f"Cleaned up: {mailbox['address']}")
except Exception as e:
print(f"Cleanup failed: {e}")
# Usage
with temporary_mailbox("minutemail.cc", expires_in=15 # 15 minutes) as mailbox:
print(f"Using mailbox: {mailbox['address']}")
# Run tests
mails = client.list_mails(mailbox["id"])
print(f"Received {len(mails['items'])} emails")
print("Mailbox automatically deleted")

Process multiple mailboxes efficiently.

from minutemail import MinuteMailClient
from typing import List, Dict, Any
client = MinuteMailClient(api_key="your-api-key")
def create_mailboxes_batch(count: int, domain: str, tag_prefix: str) -> List[Dict[str, Any]]:
"""Create multiple mailboxes with sequential tags."""
mailboxes = []
for i in range(count):
try:
mailbox = client.create_mailbox(
domain=domain,
tag=f"{tag_prefix}-{i+1}",
expires_in=30
)
mailboxes.append(mailbox)
print(f"✓ Created {i+1}/{count}: {mailbox['address']}")
except Exception as e:
print(f"✗ Failed {i+1}/{count}: {e}")
return mailboxes
def delete_mailboxes_batch(mailbox_ids: List[str]) -> None:
"""Delete multiple mailboxes."""
for i, mailbox_id in enumerate(mailbox_ids, 1):
try:
client.delete_mailbox(mailbox_id)
print(f"✓ Deleted {i}/{len(mailbox_ids)}")
except Exception as e:
print(f"✗ Failed to delete {mailbox_id}: {e}")
# Usage
mailboxes = create_mailboxes_batch(
count=5,
domain="minutemail.cc",
tag_prefix="batch-test"
)
print(f"Created {len(mailboxes)} mailboxes")
# Clean up
delete_mailboxes_batch([mb["id"] for mb in mailboxes])

Set a custom User-Agent header for API requests.

from minutemail import MinuteMailClient
import requests
# Create session with custom User-Agent
session = requests.Session()
session.headers.update({
'User-Agent': 'MyApp/1.0.0 (minutemail-sdk)'
})
client = MinuteMailClient(
api_key="your-api-key",
session=session
)
mailbox = client.create_mailbox(domain="minutemail.cc")

Log all HTTP requests and responses for debugging.

from minutemail import MinuteMailClient
import requests
import logging
# Enable debug logging
logging.basicConfig(level=logging.DEBUG)
# Enable requests library logging
import http.client as http_client
http_client.HTTPConnection.debuglevel = 1
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True
client = MinuteMailClient(api_key="your-api-key")
# All requests will be logged
mailbox = client.create_mailbox(domain="minutemail.cc")

Use the SDK through a proxy server.

from minutemail import MinuteMailClient
import requests
# Create session with proxy
session = requests.Session()
session.proxies = {
'http': 'http://proxy.example.com:8080',
'https': 'http://proxy.example.com:8080'
}
# Optional: proxy authentication
session.proxies = {
'http': 'http://user:pass@proxy.example.com:8080',
'https': 'http://user:pass@proxy.example.com:8080'
}
client = MinuteMailClient(
api_key="your-api-key",
session=session
)
mailbox = client.create_mailbox(domain="minutemail.cc")