Python SDK
The Guardhouse Python SDK provides a simple and intuitive interface for integrating Guardhouse into your Python applications.
Installation
pip
pip install guardhouse-sdk
Requirements.txt
guardhouse-sdk>=1.0.0
PyProject.toml
[dependencies]
guardhouse-sdk = ">=1.0.0"
Getting Started
Initialize Client
from guardhouse import GuardhouseClient
client = GuardhouseClient(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
domain="your-tenant.guardhouse.cloud"
)
Configuration Options
from guardhouse import GuardhouseClient
from guardhouse.config import ClientConfig
config = ClientConfig(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
domain="your-tenant.guardhouse.cloud",
api_version="v2",
timeout=30,
retry_policy=RetryPolicy(
max_retries=3,
delay=1,
backoff_factor=2
),
log_level="DEBUG"
)
client = GuardhouseClient(config=config)
User Management
List Users
# Get all users (paginated)
users = client.users.get_all()
# With pagination
users = client.users.get_all(page=1, per_page=50)
# With filtering and sorting
users = client.users.get_all(
page=1,
per_page=50,
email="john.doe@example.com",
query="john",
sort="created_at",
order="desc"
)
# Access results
for user in users.items:
print(f"{user.user_id}: {user.name} ({user.email})")
print(f"Total: {users.total}")
print(f"Page: {users.page} of {users.total_pages}")
Get User by ID
user = client.users.get("usr_123456789")
print(f"User: {user.name}")
print(f"Email: {user.email}")
print(f"Created: {user.created_at}")
print(f"Last Login: {user.last_login}")
print(f"Logins Count: {user.logins_count}")
Update User
user = client.users.get("usr_123456789")
# Update basic fields
user.name = "John Updated Doe"
user.email = "new.email@example.com"
user.phone_number = "+1-555-987-6543"
user.picture = "https://cdn.example.com/avatars/new.jpg"
# Update metadata
user.user_metadata = {
"department": "Marketing",
"employee_id": "EMP002"
}
user.app_metadata = {
"roles": ["user", "moderator"],
"permissions": ["read:users", "write:users"]
}
# Block/Unblock user
user.blocked = False
# Save changes
updated = client.users.update(user)
Create User
from guardhouse.models import CreateUserRequest
new_user = CreateUserRequest(
email="new.user@example.com",
password="SecurePassword123!",
name="New User",
connection="Username-Password-Authentication",
email_verified=True,
user_metadata={
"department": "Engineering"
}
)
created_user = client.users.create(new_user)
Delete User
client.users.delete("usr_123456789")
Batch Operations
# Update multiple users
user_ids = ["usr_123", "usr_456", "usr_789"]
for user_id in user_ids:
try:
user = client.users.get(user_id)
user.blocked = False
client.users.update(user)
print(f"Updated user: {user_id}")
except Exception as e:
print(f"Failed to update user {user_id}: {e}")
Current User Profile Management
Get Current User Profile
current_user = client.users.get_me()
print(f"User ID: {current_user.user_id}")
print(f"Name: {current_user.name}")
print(f"Email: {current_user.email}")
print(f"Email Verified: {current_user.email_verified}")
Change Password
client.users.change_password(
current_password="OldPassword123!",
new_password="NewSecurePassword123!",
confirm_password="NewSecurePassword123!"
)
Update Name
client.users.update_name(
given_name="John",
family_name="Doe"
)
Update Email
client.users.update_email(
email="new.email@example.com",
verify_email=True
)
Update Profile
client.users.update_profile(
name="John Updated Doe",
nickname="johndoe_new",
picture="https://cdn.example.com/avatars/new.jpg",
user_metadata={
"department": "Marketing",
"location": "New York"
}
)
Authentication
Get Access Token
token = client.auth.get_access_token()
print(f"Access Token: {token.access_token}")
print(f"Token Type: {token.token_type}")
print(f"Expires In: {token.expires_in} seconds")
print(f"Scope: {token.scope}")
Refresh Token
new_token = client.auth.refresh_token(refresh_token)
Revoke Token
client.auth.revoke_token(access_token)
User Login
from guardhouse.models import LoginRequest
login_result = client.auth.login(
LoginRequest(
username="user@example.com",
password="Password123!",
connection="Username-Password-Authentication"
)
)
print(f"Access Token: {login_result.access_token}")
print(f"ID Token: {login_result.id_token}")
print(f"Refresh Token: {login_result.refresh_token}")
User Logout
client.auth.logout(refresh_token)
Error Handling
Try-Except Pattern
from guardhouse.exceptions import (
GuardhouseApiException,
GuardhouseAuthenticationException,
GuardhouseValidationException
)
try:
user = client.users.get("usr_123456789")
except GuardhouseApiException as e:
# API errors (4xx, 5xx)
print(f"API Error: {e.message}")
print(f"Code: {e.code}")
print(f"Status: {e.status_code}")
print(f"Request ID: {e.request_id}")
except GuardhouseAuthenticationException as e:
# Authentication errors (invalid credentials, expired tokens)
print(f"Authentication failed: {e.message}")
except GuardhouseValidationException as e:
# Validation errors (invalid request data)
print(f"Validation failed: {e.message}")
for error in e.validation_errors:
print(f" Field: {error.field}")
print(f" Message: {error.message}")
Custom Error Handler
class CustomErrorHandler:
def handle_error(self, exception: GuardhouseApiException):
# Log error
logger.error(f"Guardhouse API error: {exception.message}")
# Send alert
alert_service.send_alert(exception)
# Register custom error handler
client = GuardhouseClient(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
domain="your-tenant.guardhouse.cloud",
error_handler=CustomErrorHandler()
)
Advanced Features
Retry Policy
from guardhouse.config import RetryPolicy
retry_policy = RetryPolicy(
max_retries=5,
delay=2,
backoff_factor=2,
retryable_status_codes=[408, 429, 500, 502, 503, 504]
)
client = GuardhouseClient(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
domain="your-tenant.guardhouse.cloud",
retry_policy=retry_policy
)
Request Timeout
client = GuardhouseClient(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
domain="your-tenant.guardhouse.cloud",
timeout=30 # 30 seconds
)
Logging
import logging
# Enable debug logging
logging.basicConfig(level=logging.DEBUG)
# Or configure specific logger
logger = logging.getLogger("guardhouse")
logger.setLevel(logging.DEBUG)
client = GuardhouseClient(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
domain="your-tenant.guardhouse.cloud"
)
Custom Logger
class CustomLogger:
def debug(self, message, *args):
print(f"[DEBUG] {message.format(*args)}")
def info(self, message, *args):
print(f"[INFO] {message.format(*args)}")
def warning(self, message, *args):
print(f"[WARN] {message.format(*args)}")
def error(self, message, *args, **kwargs):
exception = kwargs.get('exception')
print(f"[ERROR] {message.format(*args)}")
if exception:
print(f"Exception: {exception}")
client = GuardhouseClient(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
domain="your-tenant.guardhouse.cloud",
logger=CustomLogger()
)
FastAPI Integration
Dependency Injection
from fastapi import FastAPI, Depends, HTTPException
from guardhouse import GuardhouseClient
app = FastAPI()
# Initialize client
guardhouse_client = GuardhouseClient(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
domain="your-tenant.guardhouse.cloud"
)
# Dependency
def get_guardhouse_client():
return guardhouse_client
@app.get("/users")
async def get_users(client: GuardhouseClient = Depends(get_guardhouse_client)):
try:
users = client.users.get_all(page=1, per_page=50)
return {"users": [u.__dict__ for u in users.items]}
except GuardhouseApiException as e:
raise HTTPException(status_code=e.status_code, detail=e.message)
@app.get("/users/{user_id}")
async def get_user(user_id: str, client: GuardhouseClient = Depends(get_guardhouse_client)):
try:
user = client.users.get(user_id)
return user.__dict__
except GuardhouseApiException as e:
raise HTTPException(status_code=e.status_code, detail=e.message)
@app.put("/users/{user_id}")
async def update_user(user_id: str, user_data: dict, client: GuardhouseClient = Depends(get_guardhouse_client)):
try:
user = client.users.get(user_id)
user.name = user_data.get("name", user.name)
user.email = user_data.get("email", user.email)
updated = client.users.update(user)
return updated.__dict__
except GuardhouseApiException as e:
raise HTTPException(status_code=e.status_code, detail=e.message)
Authentication Middleware
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
security = HTTPBearer()
async def verify_token(credentials: HTTPAuthorizationCredentials = Depends(security)):
token = credentials.credentials
try:
# Verify token with Guardhouse
# This is a simplified example
# In production, verify JWT signature and claims
client.users.get_me() # This will throw if token is invalid
return token
except Exception:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid authentication credentials"
)
@app.get("/protected")
async def protected_route(token: str = Depends(verify_token)):
return {"message": "Access granted", "token": token}
Django Integration
Management Command
# management/commands/sync_users.py
from django.core.management.base import BaseCommand
from guardhouse import GuardhouseClient
class Command(BaseCommand):
help = 'Sync users from Guardhouse'
def handle(self, *args, **options):
client = GuardhouseClient(
client_id=settings.GUARDHOUSE_CLIENT_ID,
client_secret=settings.GUARDHOUSE_CLIENT_SECRET,
domain=settings.GUARDHOUSE_DOMAIN
)
users = client.users.get_all()
for user in users.items:
# Sync with Django
django_user, created = User.objects.get_or_create(
email=user.email,
defaults={
'username': user.email,
'first_name': user.given_name or '',
'last_name': user.family_name or ''
}
)
self.stdout.write(f"{'Created' if created else 'Updated'} user: {user.email}")
View Integration
from django.views.generic import View
from django.http import JsonResponse
from guardhouse import GuardhouseClient
class UserListView(View):
def get(self, request):
client = GuardhouseClient(
client_id=settings.GUARDHOUSE_CLIENT_ID,
client_secret=settings.GUARDHOUSE_CLIENT_SECRET,
domain=settings.GUARDHOUSE_DOMAIN
)
try:
users = client.users.get_all(page=1, per_page=50)
return JsonResponse({
'users': [u.__dict__ for u in users.items],
'total': users.total
})
except Exception as e:
return JsonResponse({'error': str(e)}, status=500)
Best Practices
- Use Async: All SDK methods are async for better performance
- Handle Errors: Always use try-except for API calls
- Implement Logging: Enable logging for debugging and monitoring
- Configure Retry: Handle transient failures gracefully
- Cache Responses: Cache frequently accessed user data
- Validate Input: Validate user input before API calls
- Use Environment Variables: Store credentials in environment variables
Environment Variables
# .env file
GUARDHOUSE_CLIENT_ID=your_client_id
GUARDHOUSE_CLIENT_SECRET=your_client_secret
GUARDHOUSE_DOMAIN=your-tenant.guardhouse.cloud
import os
from dotenv import load_dotenv
from guardhouse import GuardhouseClient
load_dotenv()
client = GuardhouseClient(
client_id=os.getenv("GUARDHOUSE_CLIENT_ID"),
client_secret=os.getenv("GUARDHOUSE_CLIENT_SECRET"),
domain=os.getenv("GUARDHOUSE_DOMAIN")
)
Additional Resources
Support
For issues, questions, or contributions: