openrouter-team-setup
Configure OpenRouter for multi-user teams with per-user keys, budget controls, and usage attribution. Triggers: 'openrouter team', 'openrouter multi-user', 'openrouter organization', 'team api keys openrouter'.
What this skill does
# OpenRouter Team Setup
## Overview
OpenRouter supports team usage through per-user API keys with individual credit limits, management keys for programmatic key provisioning, and usage attribution via headers. This skill covers key provisioning, per-user budgets, usage tracking, and governance policies for multi-user deployments.
## Key Provisioning via Management API
```python
import os, requests
MGMT_KEY = os.environ["OPENROUTER_MGMT_KEY"] # Management key (cannot call completions)
def create_team_key(name: str, credit_limit: float = 25.0) -> dict:
"""Create a new API key for a team member."""
resp = requests.post(
"https://openrouter.ai/api/v1/keys",
headers={"Authorization": f"Bearer {MGMT_KEY}"},
json={"name": name, "limit": credit_limit},
)
resp.raise_for_status()
data = resp.json()["data"]
return {
"key": data["key"], # sk-or-v1-... (shown once)
"hash": data["key_hash"], # For later identification
"name": name,
"limit": credit_limit,
}
def list_team_keys() -> list[dict]:
"""List all keys with usage and limits."""
resp = requests.get(
"https://openrouter.ai/api/v1/keys",
headers={"Authorization": f"Bearer {MGMT_KEY}"},
)
return [
{
"name": k.get("name"),
"hash": k.get("key_hash"),
"usage": k.get("usage", 0),
"limit": k.get("limit"),
"is_free_tier": k.get("is_free_tier", False),
}
for k in resp.json().get("data", [])
]
def delete_team_key(key_hash: str):
"""Revoke a team member's key."""
resp = requests.delete(
f"https://openrouter.ai/api/v1/keys/{key_hash}",
headers={"Authorization": f"Bearer {MGMT_KEY}"},
)
resp.raise_for_status()
# Provision keys for the team
for member in ["alice-backend", "bob-frontend", "carol-ml"]:
key_info = create_team_key(member, credit_limit=50.0)
print(f"Created key for {member}: {key_info['key'][:20]}...")
```
## Shared Key with User Attribution
```python
from openai import OpenAI
# Alternative: single shared key with user identification via headers
def get_client_for_user(user_id: str) -> OpenAI:
"""Create a client that attributes usage to a specific user."""
return OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=os.environ["OPENROUTER_API_KEY"],
default_headers={
"HTTP-Referer": "https://my-app.com",
"X-Title": f"my-app:{user_id}", # User shows in dashboard
},
)
# Each user's requests appear under their X-Title in the dashboard
alice_client = get_client_for_user("alice")
response = alice_client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[{"role": "user", "content": "Hello"}],
max_tokens=100,
)
```
## Per-User Budget Enforcement
```python
import sqlite3, time
def init_team_db(db_path: str = "team_usage.db"):
conn = sqlite3.connect(db_path)
conn.execute("""
CREATE TABLE IF NOT EXISTS user_usage (
user_id TEXT NOT NULL,
date TEXT NOT NULL,
total_cost REAL DEFAULT 0,
request_count INTEGER DEFAULT 0,
PRIMARY KEY (user_id, date)
)
""")
conn.execute("""
CREATE TABLE IF NOT EXISTS user_budgets (
user_id TEXT PRIMARY KEY,
daily_limit REAL NOT NULL,
model_allowlist TEXT -- JSON array of allowed model IDs
)
""")
conn.commit()
return conn
def check_user_budget(conn, user_id: str) -> bool:
"""Check if user is within their daily budget."""
today = time.strftime("%Y-%m-%d")
row = conn.execute(
"SELECT u.total_cost, b.daily_limit FROM user_usage u "
"JOIN user_budgets b ON u.user_id = b.user_id "
"WHERE u.user_id = ? AND u.date = ?",
(user_id, today),
).fetchone()
if not row:
return True # No usage yet today
return row[0] < row[1]
def record_user_usage(conn, user_id: str, cost: float):
"""Record a request's cost for a user."""
today = time.strftime("%Y-%m-%d")
conn.execute(
"""INSERT INTO user_usage (user_id, date, total_cost, request_count)
VALUES (?, ?, ?, 1)
ON CONFLICT(user_id, date) DO UPDATE SET
total_cost = total_cost + ?, request_count = request_count + 1""",
(user_id, today, cost, cost),
)
conn.commit()
```
## Team Usage Report
```python
def team_usage_report(conn) -> list[dict]:
"""Generate a team usage report for the current week."""
rows = conn.execute("""
SELECT u.user_id, SUM(u.total_cost) as weekly_cost,
SUM(u.request_count) as requests,
b.daily_limit
FROM user_usage u
JOIN user_budgets b ON u.user_id = b.user_id
WHERE u.date >= date('now', '-7 days')
GROUP BY u.user_id
ORDER BY weekly_cost DESC
""").fetchall()
return [
{
"user": row[0],
"weekly_cost": round(row[1], 4),
"requests": row[2],
"daily_limit": row[3],
}
for row in rows
]
```
## Team Key Dashboard Script
```bash
#!/bin/bash
# Show all team keys with usage
echo "=== OpenRouter Team Keys ==="
curl -s https://openrouter.ai/api/v1/keys \
-H "Authorization: Bearer $OPENROUTER_MGMT_KEY" | \
jq -r '.data[] | "\(.name)\t$\(.usage // 0 | tostring)\t/\t$\(.limit // "unlimited" | tostring)"' | \
column -t -s $'\t'
echo ""
echo "=== Total Usage ==="
curl -s https://openrouter.ai/api/v1/keys \
-H "Authorization: Bearer $OPENROUTER_MGMT_KEY" | \
jq '.data | map(.usage // 0) | add | "Total spend: $\(.)"'
```
## Model Governance
```python
# Define which models each tier can use
MODEL_ALLOWLISTS = {
"free": ["google/gemma-2-9b-it:free"],
"basic": ["openai/gpt-4o-mini", "meta-llama/llama-3.1-8b-instruct"],
"pro": ["openai/gpt-4o-mini", "openai/gpt-4o", "anthropic/claude-3.5-sonnet"],
"enterprise": None, # None = all models allowed
}
def enforce_model_policy(user_tier: str, requested_model: str) -> str:
"""Enforce model allowlist based on user tier."""
allowlist = MODEL_ALLOWLISTS.get(user_tier)
if allowlist is None:
return requested_model # Enterprise: unrestricted
if requested_model in allowlist:
return requested_model
# Downgrade to best allowed model
return allowlist[-1]
```
## Error Handling
| Error | Cause | Fix |
|-------|-------|-----|
| Management key 403 | Using API key instead of management key | Management keys are separate -- create one at openrouter.ai/keys |
| User exceeds budget | No per-user limits set | Create individual keys with credit limits |
| Attribution missing | No X-Title header | Enforce header in shared client wrapper |
| Key sprawl | Too many keys to track | Implement key lifecycle management; revoke unused keys |
## Enterprise Considerations
- Use management keys for programmatic key provisioning -- they can create/list/delete API keys but cannot make completions
- Set per-key credit limits to prevent any single user from exhausting shared budget
- Use `X-Title` header with user identifiers for dashboard-level attribution
- Implement model allowlists per user tier to control access to expensive models
- Build weekly usage reports for cost visibility and anomaly detection
- Rotate team keys on a schedule; revoke keys for departed team members immediately
## References
- Examples | Errors
- [Key Provisioning](https://openrouter.ai/docs/guides/overview/auth/provisioning-api-keys) | [Auth API](https://openrouter.ai/docs/api/reference/authentication)
Related in Backend & APIs
jfrog
IncludedInteract with the JFrog Platform via the JFrog CLI and REST/GraphQL APIs. Use this skill when the user wants to manage Artifactory repositories, upload or download artifacts, manage builds, configure permissions, manage users and groups, work with access tokens, configure JFrog CLI servers, search artifacts, manage properties, set up replication, manage JFrog Projects, run security audits or scans, look up CVE details, query exposures scan results from JFrog Advanced Security, manage release bundles and lifecycle operations, aggregate or export platform data, or perform any JFrog Platform administration task. Also use when the user mentions jf, jfrog, artifactory, xray, distribution, evidence, apptrust, onemodel, graphql, workers, mission control, curation, advanced security, exposures, or any JFrog product name.
cupynumeric-migration-readiness
IncludedPre-migration readiness assessor for porting NumPy to cuPyNumeric. Use BEFORE substantial porting work begins when the user asks whether code will scale on GPU, whether they should migrate to cuPyNumeric, which NumPy patterns transfer cleanly, what must be refactored before porting, or mentions pre-port assessment, scaling analysis, or refactor planning. Inspect the user's source code, look up NumPy usage, cross-reference the cuPyNumeric API support manifest, and distinguish distributed-scaling-friendly patterns from blockers such as unsupported APIs, scalar synchronization, host round-trips, Python/object-heavy control flow, shape/data-dependent branching, and in-place mutation hazards. Produce a verdict of READY, LIGHT REFACTOR, SIGNIFICANT REFACTOR, or NOT RECOMMENDED, with concrete refactor pointers.
alibabacloud-data-agent-skill
IncludedInvoke Alibaba Cloud Apsara Data Agent for Analytics via CLI to perform natural language-driven data analysis on enterprise databases. Data Agent for Analytics is an intelligent data analysis agent developed by Alibaba Cloud Database team for enterprise users. It automatically completes requirement analysis, data understanding, analysis insights, and report generation based on natural language descriptions. This tool supports: discovering data resources (instances/databases/tables) managed in DMS, initiating query or deep analysis sessions, real-time progress tracking, and retrieving analysis conclusions and generated reports. Use this Skill when users need to query databases, analyze data trends, generate data reports, ask questions in natural language, or mention "Data Agent", "data analysis", "database query", "SQL analysis", "data insights".
token-optimizer
IncludedReduce OpenClaw token usage and API costs through smart model routing, heartbeat optimization, budget tracking, and native 2026.2.15 features (session pruning, bootstrap size limits, cache TTL alignment). Use when token costs are high, API rate limits are being hit, or hosting multiple agents at scale. The 4 executable scripts (context_optimizer, model_router, heartbeat_optimizer, token_tracker) are local-only — no network requests, no subprocess calls, no system modifications. Reference files (PROVIDERS.md, config-patches.json) document optional multi-provider strategies that require external API keys and network access if you choose to use them. See SECURITY.md for full breakdown.
resend-cli
IncludedUse this skill when the task is specifically about operating Resend from an AI agent, terminal session, or CI job via the official resend CLI: installing/authenticating the CLI, sending/listing/updating/cancelling emails, batch sends, domains and DNS, webhooks and local listeners, inbound receiving, contacts, topics, segments, broadcasts, templates, API keys, profiles, or debugging Resend CLI/API failures. Trigger on mentions of Resend CLI, `resend`, `resend doctor`, `resend emails send`, `resend domains`, `resend webhooks listen`, `resend emails receiving`, or agent-friendly terminal automation.
alibabacloud-odps-maxframe-coding
IncludedUse this skill for MaxFrame SDK development and documentation navigation on Alibaba Cloud MaxCompute (ODPS). Helps answer MaxFrame API, concept, official example, and supported pandas API questions; create data processing programs; read/write MaxCompute tables; debug jobs (remote or local); and build custom DPE runtime images. Trigger when users mention MaxFrame, MaxCompute with MaxFrame, ODPS table processing, DPE runtime, MaxFrame docs/examples, DataFrame/Tensor operations, or GPU runtime setup. Works for both English and Chinese queries about Alibaba Cloud data processing with MaxFrame.