Team access: multiple keys with different limits
There is no dedicated "team" concept in the dashboard, but per-key limits and an allowed-model list cover almost the whole need. Here is how to set it up and what not to expect.
4 min · · Updated · API keys · бизнес
There is no separate "team" entity with roles and permissions in the dashboard — what covers this need is per-key limits. Each API key can have its own daily and monthly spend cap in dollars and its own list of models it is allowed to call. In practice, that covers almost everything needed for controlled multi-person access to one balance, without a single shared key sitting in everyone's environment variables.
The idea in short
Instead of one key for the whole team, create a separate key for each person. Each key gets its own daily/monthly spend limit and its own list of allowed models. The account balance stays one shared pool — limits cap how much a given key can draw from it, they do not create separate sub-balances.
How to set it up
- Go to /app/api-keys.
- Create a new key for each team member — name it something meaningful right away (the person's name or the service that will use it), because a key is only shown once at creation, and afterward you will tell keys apart by this name.
- On that key's page, set a daily and/or monthly spend limit in dollars.
- On the same page, restrict the list of allowed models — for example, if cheap models are enough for a junior developer's tasks, leave them
gpt-5.6-lunaandglm-5.3($0.10 per 1M tokens) orglm-5.3-flash($0.04) instead ofclaude-opus-5-5,claude-sonnet-5, andgpt-5.6-sol($0.30). Current model list:GET https://api.zukko.pro/v1/models. - Hand each person only their own key. A key is shown once at creation — if it is lost, it is simpler to issue a new one for the same person than to try to recover the old one.
What happens when someone hits their limit
A key whose daily or monthly limit is exhausted starts getting 429 with either key_daily_limit_reached or key_monthly_limit_reached, depending on which threshold tripped:
{"error": {"message": "Daily limit reached for this key", "code": "key_daily_limit_reached"}}This restricts that specific key, not the whole account — the shared balance is untouched, and the rest of the team's keys keep working normally. The person who hit the limit simply waits for the next day (the daily limit resets at 00:00 UTC) or month, or asks whoever administers the keys to raise it.
What happens when a disallowed model is called
If a key is not permitted to use a given model but the request specifies it anyway, the response is 403 with model_not_allowed_for_key:
{"error": {"message": "This model is not allowed for the given key", "code": "model_not_allowed_for_key"}}This is a technical, not just a policy, way to restrict access to expensive models — for example, if only a team lead should be working with claude-opus-5-5, that model simply is not allowed on the other keys at the settings level.
Tracking team spend
GET /v1/usage won't show spend per key: it returns the spend history for the whole account (all keys together) with cursor pagination, has no per-key filter, and the balance is likewise one per account, not per key:
curl "https://api.zukko.pro/v1/usage?limit=50" \
-H "Authorization: Bearer fetch_teammates_key"Calling it with a specific teammate's key returns the same shared account history (fields created_at, model, input_tokens, output_tokens, total_tokens, cost_cents, next_cursor), not just that person's requests. To split spend per person, log the X-Zukko-Cost-Micros header — the cost of that specific request in micro-dollars — on your own side (say, through a proxy or middleware) together with the key name, and aggregate straight from application logs. The header is only present on regular (non-streaming) responses; for streaming clients such as Cline, Roo, Claude Code, Zed, or aider that breakdown isn't possible — if you need strictly separate accounting, set up a separate account.
What this does not replace
This is not a full organization with roles, email invites, and a shared billing account with multiple logins — the dashboard has no concept of a "team member," only an account owner and their keys. If you need several people to log into the same dashboard under separate accounts with different rights over payments, that feature does not currently exist — there is only the split by key with limits and an allowed-model list, which solves the practical problem of "do not let one person accidentally or deliberately spend the whole team balance," not the problem of managing access to the dashboard itself.
Idempotency-Key across multiple services
If several of your team's services use their own keys and retry requests on network failures, make sure each service generates its own Idempotency-Key for every unique logical request (a UUID created once before the retry loop and kept the same on retries; passed in that call's headers, not in the client's default_headers, or the very next request gets a 422 idempotency_conflict) — then retrying the same request within 24 hours returns the cached result without charging again, even when the retry is triggered automatically by an HTTP client.
Setting limits in practice
A reasonable start is a small daily limit on each new key — one that covers normal daily load with a 2-3x margin — and a model list containing only the models that person actually needs. From there, raise a limit selectively for whoever it is actually blocking, based on your own per-key spend logs (/v1/usage history is shared across the account), rather than giving everyone a large limit "just in case" from day one.
zukko
Pay 25×
less
for Claude Code & ChatGPT
One fetch_* key and base URL api.zukko.pro — for Cursor, Claude Code, Codex, and any SDK.
Related articles
- OpenAI API Keys in the Open: Why You Should Not Use ThemWhere free keys on GitHub come from, why using them is dangerous for you and for the owner, and how to protect your own key from the same leak.
- GLM API Errors: Why the Request Fails and How to Fix ItA wrong model id, an overflowing 128K context, the key, the balance, limits: the typical causes of GLM API errors and a quick way to find yours.
- xAI Grok API: Connecting Grok 4.7, Price and the 256K ContextHow to call grok-4.7 through an OpenAI-compatible API, what to do about the 256K context limit and what typical requests cost. Plus a comparison with Grok 4.6.
- This organization has been disabled in the Claude API: What to DoAn Anthropic key suddenly answers "organization has been disabled". What the error is, what to check, and how to move the SDK and Claude Code to another provider.