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

  1. Go to /app/api-keys.
  2. 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.
  3. On that key's page, set a daily and/or monthly spend limit in dollars.
  4. 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-luna and glm-5.3 ($0.10 per 1M tokens) or glm-5.3-flash ($0.04) instead of claude-opus-5-5, claude-sonnet-5, and gpt-5.6-sol ($0.30). Current model list: GET https://api.zukko.pro/v1/models.
  5. 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:

bash
{"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:

bash
{"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:

bash
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.

Get API keyDocumentation

api.zukko.pro · fetch_*

Team access on zukko.pro: keys with spend limits · Zukko