Organization Management
Create and manage organizations with teams, roles, permissions, and centralized billing
Organization Structure
ParrotRouter provides a comprehensive organization management system that supports complex team structures, role-based access control, and centralized resource management. Perfect for enterprises and growing teams.
Multi-Tenant
Isolated environments for each organization
Team Management
Create teams with specific permissions
RBAC
Fine-grained role-based access control
Creating an Organization
Set up your organization with teams, roles, and billing configuration:
import requests
# Create organization
org_response = requests.post(
"https://api.parrotrouter.com/v1/organizations",
headers={
"Authorization": "Bearer your-admin-key",
"Content-Type": "application/json"
},
json={
"name": "Acme Corporation",
"slug": "acme-corp", # Unique identifier
"description": "AI-powered solutions for business",
"settings": {
"billing": {
"type": "consolidated", # or "per_team"
"payment_method_id": "pm_1234567890",
"billing_email": "finance@acme.com",
"tax_id": "US123456789",
"invoice_settings": {
"footer": "Acme Corp - Tax ID: US123456789",
"send_to": ["finance@acme.com", "accounting@acme.com"]
}
},
"security": {
"require_2fa": True,
"sso_enabled": True,
"sso_provider": "okta",
"ip_allowlist": ["203.0.113.0/24"],
"session_timeout_minutes": 60
},
"defaults": {
"timezone": "America/New_York",
"language": "en",
"date_format": "MM/DD/YYYY"
}
},
"metadata": {
"industry": "technology",
"size": "enterprise",
"founded": "2020"
}
}
)
org = org_response.json()
print(f"Organization created: {org['id']}")
# Create organization roles
roles = [
{
"name": "Organization Admin",
"slug": "org_admin",
"description": "Full administrative access",
"permissions": ["*"], # All permissions
"is_system": True
},
{
"name": "Team Lead",
"slug": "team_lead",
"description": "Manage team members and resources",
"permissions": [
"teams.read", "teams.update",
"members.read", "members.invite", "members.remove",
"api_keys.create", "api_keys.read", "api_keys.update",
"usage.read", "billing.read"
]
},
{
"name": "Developer",
"slug": "developer",
"description": "Use AI APIs and view usage",
"permissions": [
"api_keys.use",
"models.read", "models.use",
"usage.read:own", # Only own usage
"teams.read:own" # Only own team
]
},
{
"name": "Finance",
"slug": "finance",
"description": "View billing and usage data",
"permissions": [
"billing.*",
"usage.read",
"invoices.*",
"payment_methods.read"
]
},
{
"name": "Viewer",
"slug": "viewer",
"description": "Read-only access",
"permissions": [
"*.read" # All read permissions
]
}
]
for role in roles:
requests.post(
f"https://api.parrotrouter.com/v1/organizations/{org['id']}/roles",
headers={"Authorization": "Bearer your-admin-key"},
json=role
)
Team Management
Create teams within your organization with specific access controls and budgets:
Creating Teams
# Create teams with different configurations
teams_config = [
{
"name": "Engineering",
"slug": "engineering",
"description": "Product development team",
"settings": {
"budget": {
"monthly_limit": 5000.00,
"alert_threshold": 0.8,
"hard_limit": True, # Stop at limit
"rollover": False # Don't carry unused budget
},
"models": {
"allowed": [
"gpt-4-turbo-preview",
"gpt-3.5-turbo",
"claude-3-opus-20240229",
"claude-3-sonnet-20240229"
],
"blocked": ["dall-e-*"], # No image generation
"require_approval": ["gpt-4-32k"] # Expensive models
},
"features": {
"function_calling": True,
"vision": True,
"web_search": True,
"fine_tuning": False
},
"notifications": {
"usage_alerts": ["eng-leads@acme.com"],
"approval_requests": ["cto@acme.com"]
}
}
},
{
"name": "Marketing",
"slug": "marketing",
"description": "Content and marketing team",
"settings": {
"budget": {
"monthly_limit": 2000.00,
"alert_threshold": 0.9
},
"models": {
"allowed": [
"gpt-3.5-turbo",
"claude-3-sonnet-20240229",
"dall-e-3" # Allow image generation
],
"rate_limits": {
"dall-e-3": {
"requests_per_day": 100,
"requests_per_hour": 20
}
}
}
}
},
{
"name": "Data Science",
"slug": "data-science",
"description": "ML and analytics team",
"settings": {
"budget": {
"monthly_limit": 10000.00,
"require_project_tag": True
},
"models": {
"allowed": ["*"], # All models
"preferred_providers": ["openai", "anthropic"],
"allow_fine_tuning": True,
"allow_embeddings": True
},
"resources": {
"max_parallel_requests": 50,
"priority_queue": True,
"dedicated_capacity": True
}
}
}
]
# Create teams
for team_config in teams_config:
team_response = requests.post(
f"https://api.parrotrouter.com/v1/organizations/{org['id']}/teams",
headers={"Authorization": "Bearer your-admin-key"},
json=team_config
)
team = team_response.json()
print(f"Created team: {team['name']} (ID: {team['id']})")
# Set team-specific roles and permissions
team_roles = [
{
"role": "team_lead",
"permissions_override": {
"add": ["budget.modify", "members.approve_requests"],
"remove": []
}
},
{
"role": "developer",
"permissions_override": {
"add": [],
"remove": ["api_keys.create"] # Only leads can create keys
}
}
]
for role_config in team_roles:
requests.post(
f"https://api.parrotrouter.com/v1/teams/{team['id']}/roles",
headers={"Authorization": "Bearer your-admin-key"},
json=role_config
)
Managing Team Members
# Invite users to teams
def invite_team_members(team_id, members):
invitations = []
for member in members:
response = requests.post(
f"https://api.parrotrouter.com/v1/teams/{team_id}/invitations",
headers={"Authorization": "Bearer your-admin-key"},
json={
"email": member["email"],
"role": member["role"],
"message": f"You're invited to join the {member['team_name']} team at Acme Corp",
"permissions": member.get("custom_permissions", {}),
"expires_in_days": 7,
"send_email": True
}
)
invitations.append(response.json())
return invitations
# Bulk invite members
engineering_members = [
{"email": "alice@acme.com", "role": "team_lead", "team_name": "Engineering"},
{"email": "bob@acme.com", "role": "developer", "team_name": "Engineering"},
{"email": "carol@acme.com", "role": "developer", "team_name": "Engineering"},
{"email": "dave@acme.com", "role": "developer", "team_name": "Engineering",
"custom_permissions": {"add": ["deployments.manage"]}}
]
invites = invite_team_members(engineering_team_id, engineering_members)
# Accept invitation (from user's perspective)
def accept_invitation(invitation_token):
response = requests.post(
"https://api.parrotrouter.com/v1/invitations/accept",
headers={"Authorization": "Bearer user-token"},
json={
"token": invitation_token,
"accept": True
}
)
return response.json()
# Manage existing members
def update_member_role(team_id, user_id, new_role, custom_permissions=None):
response = requests.patch(
f"https://api.parrotrouter.com/v1/teams/{team_id}/members/{user_id}",
headers={"Authorization": "Bearer your-admin-key"},
json={
"role": new_role,
"permissions": custom_permissions,
"reason": "Promotion to team lead"
}
)
return response.json()
# Remove member from team
def remove_member(team_id, user_id, reassign_to=None):
response = requests.delete(
f"https://api.parrotrouter.com/v1/teams/{team_id}/members/{user_id}",
headers={"Authorization": "Bearer your-admin-key"},
json={
"reassign_resources_to": reassign_to, # Optional: reassign their resources
"revoke_access_immediately": True,
"reason": "Team restructuring"
}
)
return response.json()
Access Control & Permissions
Permission System
# Define custom permission policies
permission_policy = {
"name": "Engineering Policy",
"description": "Standard permissions for engineering team",
"statements": [
{
"effect": "allow",
"actions": [
"models:use",
"models:list",
"api_keys:use",
"usage:read"
],
"resources": [
"model:gpt-4-turbo-preview",
"model:gpt-3.5-turbo",
"model:claude-3-*"
],
"conditions": {
"ip_address": {
"type": "ip_in_range",
"value": "10.0.0.0/8" # Internal network only
},
"time": {
"type": "business_hours",
"timezone": "America/New_York",
"days": ["mon", "tue", "wed", "thu", "fri"],
"hours": {"start": "09:00", "end": "18:00"}
},
"mfa": {
"type": "required",
"max_age_minutes": 480 # 8 hours
}
}
},
{
"effect": "allow",
"actions": ["models:use"],
"resources": ["model:gpt-4-32k"],
"conditions": {
"approval": {
"type": "required",
"approvers": ["team_lead", "org_admin"],
"reason_required": True
},
"cost_limit": {
"type": "per_request",
"max_amount": 10.00
}
}
},
{
"effect": "deny",
"actions": ["*"],
"resources": ["*"],
"conditions": {
"anomaly_score": {
"type": "greater_than",
"value": 0.8 # Deny if anomaly detected
}
}
}
]
}
# Apply policy to team
requests.post(
f"https://api.parrotrouter.com/v1/teams/{team_id}/policies",
headers={"Authorization": "Bearer your-admin-key"},
json=permission_policy
)
# Create API key with team context
team_api_key = requests.post(
"https://api.parrotrouter.com/v1/api-keys",
headers={"Authorization": "Bearer team-lead-token"},
json={
"name": "Engineering Team API Key",
"team_id": engineering_team_id,
"inherit_team_permissions": True,
"additional_restrictions": {
"allowed_ips": ["10.0.1.0/24"], # Engineering subnet
"max_requests_per_minute": 100
}
}
).json()
# Check permissions for a user
permissions = requests.get(
f"https://api.parrotrouter.com/v1/users/{user_id}/permissions",
headers={"Authorization": "Bearer your-admin-key"},
params={
"team_id": team_id,
"resource": "model:gpt-4-turbo-preview",
"action": "use"
}
).json()
print(f"Can use GPT-4? {permissions['allowed']}")
print(f"Conditions: {permissions['conditions']}")
SSO & SCIM Integration
# Configure SSO with SAML
sso_config = {
"provider": "okta",
"enabled": True,
"settings": {
"sso_url": "https://acme.okta.com/app/parrotrouter/sso/saml",
"issuer": "http://www.okta.com/exk1fxpiewvjfH0h7",
"x509_cert": "-----BEGIN CERTIFICATE-----
MIID...
-----END CERTIFICATE-----",
"attribute_mapping": {
"email": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
"name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
"groups": "http://schemas.xmlsoap.org/claims/Group"
},
"role_mapping": {
"Engineering": "developer",
"Engineering-Leads": "team_lead",
"IT-Admins": "org_admin"
}
},
"provisioning": {
"scim_enabled": True,
"scim_base_url": "https://api.parrotrouter.com/scim/v2",
"scim_bearer_token": "scim_token_secure_123",
"auto_provision_users": True,
"auto_deprovision_users": True,
"sync_groups": True
}
}
# Apply SSO configuration
requests.put(
f"https://api.parrotrouter.com/v1/organizations/{org_id}/sso",
headers={"Authorization": "Bearer your-admin-key"},
json=sso_config
)
# SCIM user provisioning webhook handler
@app.post("/scim/v2/Users")
def scim_create_user(request):
scim_user = request.json
# Map SCIM attributes to ParrotRouter user
user = {
"email": scim_user["emails"][0]["value"],
"name": f"{scim_user['name']['givenName']} {scim_user['name']['familyName']}",
"external_id": scim_user["externalId"],
"active": scim_user["active"],
"groups": [g["value"] for g in scim_user.get("groups", [])]
}
# Create user in ParrotRouter
created_user = create_user_with_sso(user)
# Return SCIM response
return {
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"id": created_user["id"],
"externalId": scim_user["externalId"],
"meta": {
"resourceType": "User",
"created": created_user["created_at"],
"location": f"/scim/v2/Users/{created_user['id']}"
}
}
Billing & Cost Management
Consolidated Billing
# Configure organization billing
billing_config = {
"payment_methods": [
{
"type": "credit_card",
"is_default": True,
"details": {
"stripe_payment_method_id": "pm_1234567890"
}
},
{
"type": "invoice",
"is_default": False,
"details": {
"net_terms": 30,
"purchase_order_required": True,
"billing_address": {
"line1": "123 Main St",
"city": "New York",
"state": "NY",
"postal_code": "10001",
"country": "US"
}
}
}
],
"billing_alerts": [
{
"type": "threshold",
"amount": 5000.00,
"period": "monthly",
"notify": ["finance@acme.com", "cfo@acme.com"]
},
{
"type": "anomaly",
"sensitivity": "high",
"notify": ["security@acme.com"]
},
{
"type": "budget_exceeded",
"action": "notify", # or "suspend"
"notify": ["finance@acme.com", "team_leads"]
}
],
"cost_allocation": {
"strategy": "tag_based",
"required_tags": ["project", "environment", "team"],
"cost_centers": {
"engineering": "CC-001",
"marketing": "CC-002",
"data_science": "CC-003"
}
}
}
# Apply billing configuration
requests.put(
f"https://api.parrotrouter.com/v1/organizations/{org_id}/billing",
headers={"Authorization": "Bearer your-admin-key"},
json=billing_config
)
Usage Tracking & Reporting
# Get organization-wide usage analytics
usage_analytics = requests.get(
f"https://api.parrotrouter.com/v1/organizations/{org_id}/analytics",
headers={"Authorization": "Bearer your-admin-key"},
params={
"period": "last_30_days",
"metrics": [
"total_requests",
"total_tokens",
"total_cost",
"active_users",
"model_distribution",
"team_usage",
"error_rate",
"average_latency"
]
}
).json()
# Generate usage report
report = requests.post(
f"https://api.parrotrouter.com/v1/organizations/{org_id}/reports",
headers={"Authorization": "Bearer your-admin-key"},
json={
"type": "usage_summary",
"period": {
"start": "2024-01-01",
"end": "2024-01-31"
},
"format": "pdf", # or "csv", "json"
"sections": [
"executive_summary",
"team_breakdown",
"model_usage",
"cost_analysis",
"user_activity",
"api_performance",
"security_events"
],
"filters": {
"teams": ["engineering", "data_science"],
"min_cost": 0.01 # Exclude trivial usage
},
"delivery": {
"email": ["cfo@acme.com", "cto@acme.com"],
"webhook": "https://acme.com/webhooks/reports"
}
}
).json()
print(f"Report generated: {report['url']}")
# Set up automated reporting
requests.post(
f"https://api.parrotrouter.com/v1/organizations/{org_id}/reports/schedule",
headers={"Authorization": "Bearer your-admin-key"},
json={
"name": "Monthly Executive Report",
"schedule": "0 8 1 * *", # 8 AM on 1st of month
"report_config": {
"type": "executive_summary",
"period": "previous_month",
"format": "pdf"
},
"recipients": ["executives@acme.com"],
"enabled": True
}
)
Compliance & Auditing
Audit Logging
# Configure audit logging
audit_config = {
"enabled": True,
"retention_days": 365, # 1 year retention
"events_to_log": [
"authentication.*",
"authorization.*",
"api_key.*",
"team.*",
"member.*",
"billing.*",
"settings.*",
"data_access.*",
"security.*"
],
"export_destinations": [
{
"type": "s3",
"bucket": "acme-audit-logs",
"prefix": "parrotrouter/",
"encryption": "AES256"
},
{
"type": "siem",
"endpoint": "https://siem.acme.com/api/logs",
"api_key": "siem_key_123",
"format": "json"
}
],
"compliance": {
"standards": ["SOC2", "ISO27001", "HIPAA"],
"data_residency": "US",
"encryption_at_rest": True,
"encryption_in_transit": True
}
}
# Apply audit configuration
requests.put(
f"https://api.parrotrouter.com/v1/organizations/{org_id}/audit",
headers={"Authorization": "Bearer your-admin-key"},
json=audit_config
)
# Query audit logs
audit_logs = requests.get(
f"https://api.parrotrouter.com/v1/organizations/{org_id}/audit/logs",
headers={"Authorization": "Bearer your-admin-key"},
params={
"start_time": "2024-01-01T00:00:00Z",
"end_time": "2024-01-31T23:59:59Z",
"event_types": ["api_key.created", "member.role_changed"],
"actors": ["user:alice@acme.com"],
"resources": ["team:engineering"],
"limit": 100
}
).json()
# Generate compliance report
compliance_report = requests.post(
f"https://api.parrotrouter.com/v1/organizations/{org_id}/compliance/report",
headers={"Authorization": "Bearer your-admin-key"},
json={
"type": "SOC2_Type2",
"period": {
"start": "2023-01-01",
"end": "2023-12-31"
},
"include_evidence": True,
"auditor_access": {
"email": "auditor@compliance-firm.com",
"expires_in_days": 30
}
}
).json()
print(f"Compliance report ready: {compliance_report['secure_url']}")
Best Practices
- 1.Principle of Least Privilege
Grant minimum necessary permissions to users and teams
- 2.Regular Access Reviews
Audit and review user access quarterly
- 3.Enable SSO & 2FA
Use single sign-on and enforce two-factor authentication
- 4.Budget Controls
Set and monitor budgets for all teams
- 5.Audit Everything
Enable comprehensive audit logging for compliance