Skip to main content

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

  1. Use Async: All SDK methods are async for better performance
  2. Handle Errors: Always use try-except for API calls
  3. Implement Logging: Enable logging for debugging and monitoring
  4. Configure Retry: Handle transient failures gracefully
  5. Cache Responses: Cache frequently accessed user data
  6. Validate Input: Validate user input before API calls
  7. 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: