Installation
Install the EasyOTP Python SDK using pip:
Quick Start
from easyotp import EasyOTP
client = EasyOTP(api_key='YOUR_API_KEY')
result = client.send(
channel='sms',
recipient='+1234567890',
message='Your verification code is: {code}'
)
print('Verification ID:', result['verification_id'])
Initialization
Create a new EasyOTP client instance with your API key:
from easyotp import EasyOTP
client = EasyOTP(
api_key='YOUR_API_KEY',
base_url='https://app.easyotp.dev/api/v1'
)
Configuration Options
Your EasyOTP API key. Get it from your dashboard.
Base URL for the API. Defaults to https://app.easyotp.dev/api/v1.
Never expose your API key in client-side code. Always use the SDK from your backend server.
Methods
send()
Send a verification code via SMS, Email, or Voice.
result = client.send(
channel='sms',
recipient='+1234567890',
message='Your verification code is: {code}',
expires_in=300
)
Parameters
Communication channel. Must be one of: sms, email, or voice
Recipient address:
- For SMS/Voice: E.164 formatted phone number (e.g.,
+1234567890)
- For Email: Valid email address (e.g.,
[email protected])
Custom message template. Use {code} as a placeholder for the verification code.Default: "Your verification code is: {code}"
Email subject line (only used when channel is email)Default: "Your Verification Code"
Code expiration time in seconds. Must be between 60 and 3600.Default: 300 (5 minutes)
Custom verification code. Must be a numeric string between 4-10 digits.If not provided, a code will be automatically generated.
Returns
Always True for successful requests
Unique identifier for this verification. Use this when calling verify().
ISO 8601 timestamp when the code expires
Unique request identifier for debugging
verify()
Verify a code that was previously sent.
result = client.verify(
verification_id='11f951d5-32d1-4b49-bdda-7da248e2615c',
code='123456'
)
Parameters
The verification ID returned from the send() method
The verification code to check. Must be a numeric string between 4-10 digits.
Returns
Always True for successful requests (even if the code is invalid)
True if the code was correct and not expired, False otherwise
Human-readable result message. Possible values:
"Code verified successfully"
"Invalid code"
"Code expired"
"Code already used"
Unique request identifier for debugging
Examples
Complete Verification Flow
from easyotp import EasyOTP
import os
client = EasyOTP(api_key=os.environ.get('EASYOTP_API_KEY'))
def verify_phone_number(phone_number):
try:
result = client.send(
channel='sms',
recipient=phone_number,
message='Your verification code is: {code}',
expires_in=300
)
print('Code sent! Verification ID:', result['verification_id'])
return result['verification_id']
except Exception as e:
print(f'Failed to send code: {e}')
raise
def check_verification_code(verification_id, code):
try:
result = client.verify(
verification_id=verification_id,
code=code
)
if result['verified']:
print('Code verified successfully!')
return True
else:
print('Verification failed:', result['message'])
return False
except Exception as e:
print(f'Failed to verify code: {e}')
raise
verification_id = verify_phone_number('+1234567890')
is_valid = check_verification_code(verification_id, '123456')
Sending via Different Channels
result = client.send(
channel='sms',
recipient='+1234567890',
message='Your Acme Corp verification code is: {code}',
expires_in=300
)
Error Handling
The SDK raises exceptions for failed requests. Always wrap API calls in try-except blocks:
from easyotp import EasyOTP
from easyotp.exceptions import EasyOTPError, AuthenticationError, InsufficientCreditsError, RateLimitError
client = EasyOTP(api_key=os.environ.get('EASYOTP_API_KEY'))
try:
result = client.send(
channel='sms',
recipient='+1234567890',
message='Your verification code is: {code}'
)
print('Success:', result['verification_id'])
except AuthenticationError:
print('Invalid API key')
except InsufficientCreditsError:
print('Insufficient credits')
except RateLimitError as e:
print(f'Rate limit exceeded. Retry after {e.retry_after} seconds')
except EasyOTPError as e:
print(f'Error: {e.message}')
Flask Integration Example
from flask import Flask, request, jsonify
from easyotp import EasyOTP
import os
app = Flask(__name__)
client = EasyOTP(api_key=os.environ.get('EASYOTP_API_KEY'))
sessions = {}
@app.route('/api/send-code', methods=['POST'])
def send_code():
try:
data = request.json
phone_number = data.get('phoneNumber')
result = client.send(
channel='sms',
recipient=phone_number,
message='Your verification code is: {code}',
expires_in=300
)
import uuid
session_id = str(uuid.uuid4())
sessions[session_id] = {
'phone_number': phone_number,
'verification_id': result['verification_id']
}
return jsonify({'sessionId': session_id})
except Exception as e:
return jsonify({'error': str(e)}), 500
@app.route('/api/verify-code', methods=['POST'])
def verify_code():
try:
data = request.json
session_id = data.get('sessionId')
code = data.get('code')
session = sessions.get(session_id)
if not session:
return jsonify({'error': 'Invalid session'}), 400
result = client.verify(
verification_id=session['verification_id'],
code=code
)
if result['verified']:
del sessions[session_id]
return jsonify({'success': True})
else:
return jsonify({'success': False, 'message': result['message']})
except Exception as e:
return jsonify({'error': str(e)}), 500
if __name__ == '__main__':
app.run()
Django Integration Example
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
from easyotp import EasyOTP
import os
import json
client = EasyOTP(api_key=os.environ.get('EASYOTP_API_KEY'))
@csrf_exempt
@require_http_methods(["POST"])
def send_code(request):
try:
data = json.loads(request.body)
phone_number = data.get('phoneNumber')
result = client.send(
channel='sms',
recipient=phone_number,
message='Your verification code is: {code}',
expires_in=300
)
import uuid
session_id = str(uuid.uuid4())
request.session[session_id] = {
'phone_number': phone_number,
'verification_id': result['verification_id']
}
return JsonResponse({'sessionId': session_id})
except Exception as e:
return JsonResponse({'error': str(e)}, status=500)
@csrf_exempt
@require_http_methods(["POST"])
def verify_code(request):
try:
data = json.loads(request.body)
session_id = data.get('sessionId')
code = data.get('code')
session = request.session.get(session_id)
if not session:
return JsonResponse({'error': 'Invalid session'}, status=400)
result = client.verify(
verification_id=session['verification_id'],
code=code
)
if result['verified']:
del request.session[session_id]
return JsonResponse({'success': True})
else:
return JsonResponse({'success': False, 'message': result['message']})
except Exception as e:
return JsonResponse({'error': str(e)}, status=500)
Error Handling
The SDK raises custom exceptions for different error types:
Exception Classes
EasyOTPError: Base exception for all SDK errors
AuthenticationError: Raised for 401 errors (invalid API key)
InsufficientCreditsError: Raised for 402 errors (insufficient credits)
ForbiddenError: Raised for 403 errors (API key disabled)
NotFoundError: Raised for 404 errors (verification not found)
RateLimitError: Raised for 429 errors (rate limit exceeded)
ServerError: Raised for 500 errors (internal server error)
Error Object Properties
All exceptions include:
message: Human-readable error message
status_code: HTTP status code
request_id: Unique request identifier for debugging
retry_after: Seconds to wait before retrying (for rate limit errors)
Common Error Codes
| Status Code | Exception | Solution |
|---|
400 | EasyOTPError | Check your request parameters |
401 | AuthenticationError | Verify your API key is correct |
402 | InsufficientCreditsError | Add credits to your account |
403 | ForbiddenError | API key is disabled |
404 | NotFoundError | Verification ID doesn’t exist |
429 | RateLimitError | Wait for retry_after seconds |
500 | ServerError | Contact support with request_id |
Type Hints
The SDK includes type hints for better IDE support:
from easyotp import EasyOTP
from typing import Dict, Any
client = EasyOTP(api_key='YOUR_API_KEY')
def send_otp(phone_number: str) -> Dict[str, Any]:
return client.send(
channel='sms',
recipient=phone_number,
message='Your code is: {code}'
)
def verify_otp(verification_id: str, code: str) -> Dict[str, Any]:
return client.verify(
verification_id=verification_id,
code=code
)
Best Practices
Store API keys securely: Use environment variables and never commit them to version control.
Handle errors gracefully: Always wrap SDK calls in try-except blocks and provide meaningful error messages to users.
Use appropriate expiration times:
- SMS/Voice: 2-5 minutes
- Email: 10-15 minutes
Keep verification IDs server-side: Never expose verification IDs in URLs or client-side code. Store them server-side associated with user sessions.
Rate limiting: The SDK automatically handles rate limit responses. Check for retry_after in exception objects to inform users when they can retry.
Use environment variables: Store your API key in environment variables for better security:import os
client = EasyOTP(api_key=os.environ.get('EASYOTP_API_KEY'))
Additional Resources