Skip to navigation

API Patterns & Best Practices

API Patterns & Best Practices

Pagination

Handle large result sets with pagination:

def get_all_audit_logs(org_id, start_date):
"""Fetch all audit logs with pagination"""
page = 1
all_logs = []
while True:
response = requests.get(
'https://api.governanceai.com/v1/audit/logs',
headers=headers,
params={
'org_id': org_id,
'start_date': start_date,
'page': page,
'page_size': 100
}
)
data = response.json()
all_logs.extend(data['entries'])
# Check if there are more pages
if data['pagination']['page'] >= data['pagination']['total_pages']:
break
page += 1
return all_logs

Retry Logic

Implement exponential backoff for retries:

import time
def make_request_with_retry(url, method='POST', data=None, max_retries=3):
"""Make request with exponential backoff retry"""
for attempt in range(max_retries):
try:
if method == 'POST':
response = requests.post(url, headers=headers, json=data, timeout=10)
else:
response = requests.get(url, headers=headers, timeout=10)
if response.status_code == 429: # Rate limit
wait_time = 2 ** attempt # 1, 2, 4 seconds
print(f"Rate limited. Waiting {wait_time}s...")
time.sleep(wait_time)
continue
response.raise_for_status()
return response.json()
except requests.exceptions.Timeout:
if attempt < max_retries - 1:
wait_time = 2 ** attempt
time.sleep(wait_time)
continue
raise
except requests.exceptions.RequestException as e:
if attempt < max_retries - 1:
wait_time = 2 ** attempt
time.sleep(wait_time)
continue
raise
raise Exception("Max retries exceeded")

Rate Limit Handling

Check rate limit headers:

def handle_rate_limits(response):
"""Extract rate limit information from response headers"""
remaining = response.headers.get('X-RateLimit-Remaining', 'unknown')
limit = response.headers.get('X-RateLimit-Limit', 'unknown')
reset_time = response.headers.get('X-RateLimit-Reset', 'unknown')
print(f"Rate Limit: {remaining}/{limit}")
print(f"Reset at: {reset_time}")
if int(remaining) < 10:
print("Warning: Approaching rate limit")
return {
'remaining': remaining,
'limit': limit,
'reset_time': reset_time
}

Batch Operations

Process multiple items efficiently:

def batch_evaluate_guardrails(messages_list, batch_size=10):
"""Evaluate multiple messages in batches"""
results = []
for i in range(0, len(messages_list), batch_size):
batch = messages_list[i:i + batch_size]
for message in batch:
result = requests.post(
'https://api.governanceai.com/v1/guardrails/evaluate',
headers=headers,
json={
'messages': [{'role': 'user', 'content': message}],
'context': {'org_id': ORG_ID, 'user_id': 'batch_user'}
}
).json()
results.append(result)
# Small delay between requests
time.sleep(0.1)
return results

Caching Responses

Cache API responses to reduce load:

import json
from datetime import datetime, timedelta
cache = {}
def get_cached_policy(policy_id, cache_ttl_minutes=60):
"""Get policy with caching"""
cache_key = f"policy_{policy_id}"
# Check cache
if cache_key in cache:
cached_data, cached_time = cache[cache_key]
if datetime.now() - cached_time < timedelta(minutes=cache_ttl_minutes):
return cached_data
# Fetch from API
response = requests.get(
f'https://api.governanceai.com/v1/policies/{policy_id}',
headers=headers
).json()
# Store in cache
cache[cache_key] = (response, datetime.now())
return response

Webhook Handling

Process webhook events from GovernanceAI:

from flask import Flask, request
import hmac
import hashlib
app = Flask(__name__)
WEBHOOK_SECRET = os.getenv('GOVERNANCEAI_WEBHOOK_SECRET')
def verify_webhook_signature(payload, signature):
"""Verify webhook signature"""
expected = hmac.new(
WEBHOOK_SECRET.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
@app.route('/webhooks/governanceai', methods=['POST'])
def handle_webhook():
"""Handle GovernanceAI webhook"""
signature = request.headers.get('X-Signature')
payload = request.get_data()
# Verify signature
if not verify_webhook_signature(payload, signature):
return {'error': 'Invalid signature'}, 401
# Process event
event = request.json
print(f"Received event: {event['type']}")
if event['type'] == 'vulnerability_detected':
handle_vulnerability(event['data'])
elif event['type'] == 'scan_completed':
handle_scan_complete(event['data'])
return {'status': 'ok'}, 200

Monitoring & Metrics

Track API usage patterns:

from collections import defaultdict
from datetime import datetime
metrics = defaultdict(list)
def track_api_call(endpoint, duration_ms, status_code):
"""Track API metrics"""
metrics[endpoint].append({
'timestamp': datetime.now(),
'duration_ms': duration_ms,
'status_code': status_code
})
def get_metrics_summary(endpoint):
"""Get metrics summary for endpoint"""
calls = metrics[endpoint]
durations = [c['duration_ms'] for c in calls]
return {
'total_calls': len(calls),
'avg_duration_ms': sum(durations) / len(durations),
'p95_duration_ms': sorted(durations)[int(len(durations) * 0.95)],
'p99_duration_ms': sorted(durations)[int(len(durations) * 0.99)]
}

Best Practices

✅ Do:

  • Use environment variables for credentials
  • Implement retry logic with exponential backoff
  • Cache responses when appropriate
  • Monitor rate limits
  • Verify webhook signatures
  • Handle all error codes
  • Log API calls for debugging
  • Use batch operations for multiple items

❌ Don’t:

  • Hardcode API keys
  • Ignore rate limit headers
  • Make synchronous calls in loops
  • Store sensitive data in logs
  • Skip error handling
  • Make unlimited retries
  • Share API responses publicly

Next Steps