Getting Started
Getting Started
Section titled “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
Installation
Section titled “Installation”Install from PyPI:
pip install minutemail-sdkFor development:
git clone https://github.com/minutemailco/minutemail-pythoncd minutemail-pythonpip install -e .Requirements
Section titled “Requirements”- Python 3.9+
requests >= 2.31.0
Quick Example
Section titled “Quick Example”from minutemail import MinuteMailClient, APIError
# Initialize the clientclient = 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})")Authentication
Section titled “Authentication”The SDK requires an API key for all authenticated operations.
Basic Configuration
Section titled “Basic Configuration”from minutemail import MinuteMailClient
client = MinuteMailClient(api_key="mmak_YOUR_API_KEY")Constructor Parameters
Section titled “Constructor Parameters”| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
api_key | str | ✅ | - | Your MinuteMail API key |
base_url | str | ❌ | https://api.minutemail.co | API base URL (no /v1 suffix) |
timeout | float | ❌ | 10.0 | Request timeout in seconds |
session | requests.Session | ❌ | None | Custom session for connection pooling |
Environment Variables
Section titled “Environment Variables”Store your API key securely using environment variables:
import osfrom minutemail import MinuteMailClient
client = MinuteMailClient( api_key=os.getenv("MINUTEMAIL_API_KEY"), base_url=os.getenv("MINUTEMAIL_BASE_URL", "https://api.minutemail.co"))Custom Base URL
Section titled “Custom Base URL”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)Custom Timeout
Section titled “Custom Timeout”Adjust timeout for slow networks or long-running operations:
client = MinuteMailClient( api_key="your-api-key", timeout=30.0 # 30 seconds)Getting an API Key
Section titled “Getting an API Key”- Log in to your MinuteMail dashboard at MinuteMail
- Click your profile menu → API Keys
- Click Create API Key
- (Optional) Configure Domain Restrictions to limit where the key can be used
- Copy and securely store your key
Security Note: Never commit API keys to version control. Use environment variables or secret management tools.
Domain Restrictions
Section titled “Domain Restrictions”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 subdomainslocalhost:3000- Development domains with ports
If your SDK requests receive 403 Forbidden errors mentioning domain restrictions, verify that:
- Your API key has the correct domains configured in the dashboard
- Your application is running on an allowed domain
- Your requests include proper
Origin,Referer, orHostheaders
Error Handling
Section titled “Error Handling”The SDK raises specific exceptions for different error conditions.
Exception Types
Section titled “Exception Types”APIError
Section titled “APIError”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 codeerror(str): Error code from APImessage(str): Human-readable error message
TransportError
Section titled “TransportError”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 logicMinuteMailError
Section titled “MinuteMailError”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}")Common Error Scenarios
Section titled “Common Error Scenarios”Invalid API Key
Section titled “Invalid API Key”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.")Quota Exceeded
Section titled “Quota Exceeded”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.")Resource Not Found
Section titled “Resource Not Found”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.")Domain Restriction Error
Section titled “Domain Restriction Error”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.")Network Timeout
Section titled “Network Timeout”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.")Best Practices
Section titled “Best Practices”Comprehensive Error Handling
Section titled “Comprehensive Error Handling”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
# Usagemailbox = 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")Retry Logic with Exponential Backoff
Section titled “Retry Logic with Exponential Backoff”import timefrom 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)
# Usagetry: 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}")Logging Errors
Section titled “Logging Errors”import loggingfrom minutemail import APIError, TransportError
# Configure logginglogging.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
# Usagetry: mailbox = create_mailbox_with_logging( domain="minutemail.cc", expires_in=30 )except Exception: logger.exception("Failed to create mailbox")Error Code Reference
Section titled “Error Code Reference”| Status Code | Error Code | Description | Action |
|---|---|---|---|
400 | bad_request | Invalid request (malformed JSON, missing fields) | Check request parameters |
400 | invalid_duration | Invalid duration format | Use formats like "30m", "2h" |
401 | unauthorized | Invalid or missing API key | Verify API key |
403 | forbidden | Access denied or domain restriction failed | Check permissions and domain configuration |
404 | not_found | Resource not found | Verify resource ID |
409 | conflict | Resource conflict | Check for duplicate resources |
429 | rate_limit_exceeded | Too many requests | Implement backoff |
429 | quota_exceeded | Usage quota exceeded | Upgrade plan or wait for reset |
500 | internal_error | Server error | Retry or contact support |
503 | service_unavailable | Service unavailable | Retry after delay |
Advanced Usage
Section titled “Advanced Usage”Custom Session with Retry Logic
Section titled “Custom Session with Retry Logic”Use a custom requests.Session for connection pooling and automatic retries.
from minutemail import MinuteMailClientimport requestsfrom requests.adapters import HTTPAdapterfrom urllib3.util.retry import Retry
# Create session with retry strategysession = 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 sessionclient = MinuteMailClient( api_key="your-api-key", timeout=30.0, session=session)
# Use client normally - retries happen automaticallymailbox = client.create_mailbox(domain="minutemail.cc")Connection Pooling
Section titled “Connection Pooling”Improve performance for multiple requests by reusing connections.
from minutemail import MinuteMailClientimport requests
# Create session with connection poolingsession = 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 connectionfor 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']}")Environment-Based Configuration
Section titled “Environment-Based Configuration”Load configuration from environment variables.
import osfrom 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 )
# Usageconfig = MinuteMailConfig()client = config.create_client()
mailbox = client.create_mailbox(domain="minutemail.cc")print(f"Created: {mailbox['address']}")Example .env file:
MINUTEMAIL_API_KEY=mmak_FKI5IKBJ4FSZJLUFGJ3IMF4A55W2OZW7YMLWD3JI33IVUGDEJXLQMINUTEMAIL_BASE_URL=https://api.minutemail.coMINUTEMAIL_TIMEOUT=30.0Async Wrapper (Using asyncio)
Section titled “Async Wrapper (Using asyncio)”Wrap the synchronous SDK in async functions for integration with async code.
import asynciofrom concurrent.futures import ThreadPoolExecutorfrom 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) )
# Usageasync 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())Context Manager for Automatic Cleanup
Section titled “Context Manager for Automatic Cleanup”Create a context manager for automatic mailbox cleanup.
from minutemail import MinuteMailClientfrom contextlib import contextmanager
client = MinuteMailClient(api_key="your-api-key")
@contextmanagerdef 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}")
# Usagewith 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")Batch Operations
Section titled “Batch Operations”Process multiple mailboxes efficiently.
from minutemail import MinuteMailClientfrom 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}")
# Usagemailboxes = create_mailboxes_batch( count=5, domain="minutemail.cc", tag_prefix="batch-test")
print(f"Created {len(mailboxes)} mailboxes")
# Clean updelete_mailboxes_batch([mb["id"] for mb in mailboxes])Custom User-Agent
Section titled “Custom User-Agent”Set a custom User-Agent header for API requests.
from minutemail import MinuteMailClientimport requests
# Create session with custom User-Agentsession = 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")Debugging with Request/Response Logging
Section titled “Debugging with Request/Response Logging”Log all HTTP requests and responses for debugging.
from minutemail import MinuteMailClientimport requestsimport logging
# Enable debug logginglogging.basicConfig(level=logging.DEBUG)
# Enable requests library loggingimport http.client as http_clienthttp_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 loggedmailbox = client.create_mailbox(domain="minutemail.cc")Proxy Configuration
Section titled “Proxy Configuration”Use the SDK through a proxy server.
from minutemail import MinuteMailClientimport requests
# Create session with proxysession = requests.Session()session.proxies = { 'http': 'http://proxy.example.com:8080', 'https': 'http://proxy.example.com:8080'}
# Optional: proxy authenticationsession.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")