Back to Examples
Python
Integrate GuardCrow into your Python applications using requests or httpx.
Basic Example
A simple example using the requests library:
analyze.pypython
import osimport requestsdef analyze_content(content: str) -> dict:"""Analyze content for toxicity and sentiment."""response = requests.post("https://api.guardcrow.com/v1/analyze",headers={"X-API-Key": os.environ["GUARDCROW_API_KEY"],"Content-Type": "application/json",},json={"content": content},)response.raise_for_status()return response.json()# Usageresult = analyze_content("Hello, this is a test message")print(f"Passed: {result['passed']}, Score: {result['score']}")
Client Class with Retry Logic
A complete client implementation with error handling and automatic retries:
guardcrow.pypython
import osimport timefrom typing import Optionalfrom dataclasses import dataclassimport requestsfrom requests.exceptions import RequestException@dataclassclass AnalysisResult:passed: boolscore: intsentiment: strdescription: strcategories: list[str]processing_time_ms: intclass GuardCrowError(Exception):"""Base exception for GuardCrow errors."""def __init__(self, code: str, message: str, status: int):self.code = codeself.message = messageself.status = statussuper().__init__(message)class RateLimitError(GuardCrowError):"""Raised when rate limit is exceeded."""def __init__(self, message: str, reset_time: Optional[int] = None):super().__init__("RATE_LIMIT_EXCEEDED", message, 429)self.reset_time = reset_timeclass GuardCrowClient:"""Client for the GuardCrow API."""def __init__(self,api_key: Optional[str] = None,base_url: str = "https://api.guardcrow.com/v1",max_retries: int = 3,timeout: int = 30,):self.api_key = api_key or os.environ.get("GUARDCROW_API_KEY")if not self.api_key:raise ValueError("API key is required")self.base_url = base_urlself.max_retries = max_retriesself.timeout = timeoutself.session = requests.Session()self.session.headers.update({"X-API-Key": self.api_key,"Content-Type": "application/json",})def analyze(self,content: str,metadata: Optional[dict] = None,) -> AnalysisResult:"""Analyze content for toxicity and sentiment.Args:content: Text to analyze (max 10,000 characters)metadata: Optional metadata (source, user_id, etc.)Returns:AnalysisResult with moderation detailsRaises:GuardCrowError: On API errorsRateLimitError: When rate limited"""payload = {"content": content}if metadata:payload["metadata"] = metadatalast_error = Nonefor attempt in range(self.max_retries):try:response = self.session.post(f"{self.base_url}/analyze",json=payload,timeout=self.timeout,)# Handle rate limitingif response.status_code == 429:reset_time = response.headers.get("X-RateLimit-Reset")wait_seconds = (int(reset_time) - int(time.time())if reset_timeelse 2 ** attempt)if attempt < self.max_retries - 1:time.sleep(max(wait_seconds, 1))continueraise RateLimitError("Rate limit exceeded",int(reset_time) if reset_time else None,)# Handle other errorsif not response.ok:error_data = response.json().get("error", {})raise GuardCrowError(code=error_data.get("code", "UNKNOWN"),message=error_data.get("message", "Unknown error"),status=response.status_code,)data = response.json()return AnalysisResult(passed=data["passed"],score=data["score"],sentiment=data["sentiment"],description=data["description"],categories=data["categories"],processing_time_ms=data["processingTimeMs"],)except RequestException as e:last_error = eif attempt < self.max_retries - 1:time.sleep(2 ** attempt)raise last_error or GuardCrowError("NETWORK_ERROR", "Request failed", 0)def health_check(self) -> dict:"""Check API health status."""response = self.session.get(f"{self.base_url}/health",timeout=self.timeout,)response.raise_for_status()return response.json()# Usageif __name__ == "__main__":client = GuardCrowClient()try:result = client.analyze("This is a test message",metadata={"source": "user-comments"},)print(f"Passed: {result.passed}")print(f"Score: {result.score}")print(f"Sentiment: {result.sentiment}")except RateLimitError as e:print(f"Rate limited. Reset at: {e.reset_time}")except GuardCrowError as e:print(f"API error: {e.code} - {e.message}")
Async Version (httpx)
For async applications using httpx:
guardcrow_async.pypython
import osimport asynciofrom typing import Optionalimport httpxclass AsyncGuardCrowClient:"""Async client for the GuardCrow API."""def __init__(self, api_key: Optional[str] = None):self.api_key = api_key or os.environ.get("GUARDCROW_API_KEY")self.base_url = "https://api.guardcrow.com/v1"async def analyze(self, content: str) -> dict:"""Analyze content asynchronously."""async with httpx.AsyncClient() as client:response = await client.post(f"{self.base_url}/analyze",headers={"X-API-Key": self.api_key,"Content-Type": "application/json",},json={"content": content},timeout=30.0,)response.raise_for_status()return response.json()async def analyze_batch(self, contents: list[str]) -> list[dict]:"""Analyze multiple contents concurrently."""tasks = [self.analyze(content) for content in contents]return await asyncio.gather(*tasks, return_exceptions=True)# Usageasync def main():client = AsyncGuardCrowClient()# Single analysisresult = await client.analyze("Test message")print(result)# Batch analysiscontents = ["First message to check","Second message to check","Third message to check",]results = await client.analyze_batch(contents)for content, result in zip(contents, results):if isinstance(result, Exception):print(f"Error analyzing: {content}")else:print(f"{content[:30]}... -> Score: {result['score']}")asyncio.run(main())
FastAPI Integration
Create a moderation middleware for FastAPI:
main.pypython
from fastapi import FastAPI, HTTPException, Dependsfrom pydantic import BaseModelimport httpximport osapp = FastAPI()GUARDCROW_API_KEY = os.environ["GUARDCROW_API_KEY"]class Comment(BaseModel):content: struser_id: strclass ModerationResult(BaseModel):passed: boolscore: intsentiment: strasync def moderate_content(content: str) -> ModerationResult:"""Call GuardCrow API to moderate content."""async with httpx.AsyncClient() as client:response = await client.post("https://api.guardcrow.com/v1/analyze",headers={"X-API-Key": GUARDCROW_API_KEY,"Content-Type": "application/json",},json={"content": content},timeout=30.0,)if response.status_code == 429:raise HTTPException(status_code=503,detail="Service temporarily unavailable",)response.raise_for_status()data = response.json()return ModerationResult(passed=data["passed"],score=data["score"],sentiment=data["sentiment"],)@app.post("/comments")async def create_comment(comment: Comment):# Moderate the contentmoderation = await moderate_content(comment.content)if not moderation.passed:raise HTTPException(status_code=400,detail=f"Content blocked: {moderation.sentiment}",)# Save the comment (your logic here)return {"status": "created","moderation_score": moderation.score,}@app.post("/moderate")async def moderate_endpoint(comment: Comment):"""Public moderation endpoint."""result = await moderate_content(comment.content)return result
Django Integration
Create a reusable validator for Django models:
validators.pypython
import osimport requestsfrom django.core.exceptions import ValidationErrordef validate_content_safety(content: str, max_score: int = 6) -> None:"""Django validator for content moderation.Usage in a model:content = models.TextField(validators=[validate_content_safety])"""try:response = requests.post("https://api.guardcrow.com/v1/analyze",headers={"X-API-Key": os.environ["GUARDCROW_API_KEY"],"Content-Type": "application/json",},json={"content": content},timeout=30,)response.raise_for_status()result = response.json()if result["score"] > max_score:raise ValidationError(f"Content flagged: {result['description']}",code="content_unsafe",params={"score": result["score"]},)except requests.RequestException:# Don't block on API errorspass# Usage in models.pyfrom django.db import modelsfrom .validators import validate_content_safetyclass Comment(models.Model):content = models.TextField(validators=[validate_content_safety])user = models.ForeignKey("User", on_delete=models.CASCADE)created_at = models.DateTimeField(auto_now_add=True)
Installation & Setup
Install the required dependencies:
Terminalbash
# Using pippip install requests# Or for async supportpip install httpx
Set your API key as an environment variable:
.envbash
GUARDCROW_API_KEY=sk_live_your_api_key_here