How to give your team AI access without handing out API keys

A practical guide to running a LiteLLM gateway — one server that holds your AI provider keys, and a virtual key for every person or team with its own models, budget, rate limit and expiry. Written by the team that runs one in production.

Why shared API keys go wrong

  • One runaway script spends the month. A shared key has no per-person limit, so one loop or one curious intern can burn the whole budget overnight.
  • Nobody knows who sent what. With one key for everyone, the provider bill is a single number. You cannot see which team, tool or person drove it.
  • You cannot revoke one person. When someone leaves, the only fix is rotating the key — and breaking every tool that uses it.
  • Keys leak. Shared keys end up in chat threads, spreadsheets and code repositories, where anyone can copy them.
  • Credits are stuck in personal accounts. Cloud credits or company accounts tied to one person’s login become a problem the day that person moves on.

The pattern: one gateway, many keys

LiteLLM is an open-source proxy that speaks the OpenAI API and forwards requests to more than a hundred providers. Your people never see a provider key — they get a virtual key that the gateway checks, limits and records.

Your people & tools

Staff laptops Chat app Scripts & agents

virtual key each

LiteLLM gateway

  • allowed models per key
  • hard budgets & rate limits
  • expiry & instant block
  • spend log per person & team

provider keys stay here

AI providers

OpenAI · Anthropic Google Vertex AI (your credits) DeepSeek · Qwen · others

Set it up, step by step

  1. 01 Pick a home for the gateway

    A small Linux server with Docker is enough to start — the gateway is light; Postgres stores keys and spend. Give it a domain with TLS, and keep the admin interface off the public internet (VPN, tailnet or an IP allow-list).

  2. 02 Create the two secrets that matter

    The master key is the admin key — it creates every other key and must start with sk-. The salt key encrypts provider credentials stored in the database; set it once and never change it after you add models. Keep both in your secret manager, not in the repository.

    shell — writes .env (keep it out of git)
    umask 077
    {
      echo "LITELLM_MASTER_KEY=sk-$(openssl rand -hex 24)"
      echo "LITELLM_SALT_KEY=$(openssl rand -hex 32)"
      echo "POSTGRES_PASSWORD=$(openssl rand -hex 16)"
    } > .env
    
    # then add your provider keys — they live only on this server
    echo 'OPENAI_API_KEY=...'    >> .env
    echo 'ANTHROPIC_API_KEY=...' >> .env
    echo 'DEEPSEEK_API_KEY=...'  >> .env
  3. 03 Describe your models

    Each entry maps the name your people call to a real provider model. Using cloud credits? Point a model at a specific Google Cloud project — one project per department or course keeps budgets separate.

    config.yaml
    model_list:
      - model_name: gpt-4o-mini
        litellm_params:
          model: openai/gpt-4o-mini
          api_key: os.environ/OPENAI_API_KEY
    
      - model_name: claude-sonnet
        litellm_params:
          model: anthropic/claude-sonnet-4-5
          api_key: os.environ/ANTHROPIC_API_KEY
    
      # Google Cloud credits: one GCP project per team or course
      - model_name: gemini-teaching
        litellm_params:
          model: vertex_ai/gemini-2.5-pro
          vertex_project: "faculty-course-a"
          vertex_location: "asia-southeast1"   # a region where the model is offered
          vertex_credentials: os.environ/VERTEX_SA_COURSE_A
    
      - model_name: deepseek-chat
        litellm_params:
          model: deepseek/deepseek-chat
          api_key: os.environ/DEEPSEEK_API_KEY
    
    litellm_settings:
      drop_params: true                # ignore params a provider doesn't support
      turn_off_message_logging: true   # no prompts in logging callbacks
    
    general_settings:
      master_key: os.environ/LITELLM_MASTER_KEY
      database_url: os.environ/DATABASE_URL

    Model names change often — use the current model ids from each provider’s console. The names on the left are yours; keep them stable so tools never need editing.

  4. 04 Run it

    LiteLLM ships a Docker image. Pin a release tag in production so upgrades and rollbacks are deliberate, and check the liveness endpoint once it starts.

    docker-compose.yml
    services:
      litellm:
        image: ghcr.io/berriai/litellm:main-stable   # pin a release tag in production
        command: ["--config", "/app/config.yaml", "--port", "4000"]
        volumes:
          - ./config.yaml:/app/config.yaml:ro
        env_file: .env
        environment:
          DATABASE_URL: postgresql://llmproxy:${POSTGRES_PASSWORD}@db:5432/litellm
        ports:
          - "127.0.0.1:4000:4000"   # expose through your TLS proxy, not directly
        depends_on:
          db:
            condition: service_healthy
        restart: unless-stopped
    
      db:
        image: postgres:16
        environment:
          POSTGRES_DB: litellm
          POSTGRES_USER: llmproxy
          POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
        volumes:
          - litellm_pg:/var/lib/postgresql/data
        healthcheck:
          test: ["CMD-SHELL", "pg_isready -d litellm -U llmproxy"]
          interval: 5s
          retries: 10
        restart: unless-stopped
    
    volumes:
      litellm_pg:
    shell
    docker compose up -d
    curl -s http://127.0.0.1:4000/health/liveliness
  5. 05 Create a team for each group, with a budget

    Teams carry the models a group may use and a spend cap that resets on a schedule. Requests are rejected once the team crosses its budget.

    shell
    curl -s https://llm.example.com/team/new \
      -H "Authorization: Bearer $LITELLM_MASTER_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "team_alias": "finance",
        "models": ["gpt-4o-mini", "claude-sonnet"],
        "max_budget": 200,
        "budget_duration": "1mo"
      }'
  6. 06 Issue a key per person

    Each virtual key names its owner, belongs to a team, lists the models it may call, and has its own budget, rate limit and expiry. Hand out this key — never the provider key.

    shell
    curl -s https://llm.example.com/key/generate \
      -H "Authorization: Bearer $LITELLM_MASTER_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "key_alias": "priya-laptop",
        "user_id": "[email protected]",
        "team_id": "<team_id from the previous step>",
        "models": ["gpt-4o-mini", "claude-sonnet"],
        "max_budget": 20,
        "budget_duration": "30d",
        "rpm_limit": 60,
        "duration": "90d"
      }'
  7. 07 Point your tools at the gateway

    The gateway speaks the OpenAI API, so most tools only need a base URL and the person’s virtual key — SDKs, chat apps such as Open WebUI or LibreChat, and coding agents that accept an OpenAI-compatible endpoint.

    shell
    export OPENAI_BASE_URL=https://llm.example.com/v1
    export OPENAI_API_KEY=sk-...   # the person's virtual key
    python
    from openai import OpenAI
    
    client = OpenAI()  # reads OPENAI_BASE_URL and OPENAI_API_KEY
    reply = client.chat.completions.create(
        model="claude-sonnet",  # the name from your config, not the provider's
        messages=[{"role": "user", "content": "Summarise this policy in 3 bullets."}],
    )
    print(reply.choices[0].message.content)
  8. 08 Watch spend, cap it, revoke it

    Every call is recorded against the key, the person and the team. Block a key the moment someone leaves or a device is lost — nobody else is affected.

    shell
    # spend and limits for one key
    curl -s "https://llm.example.com/key/info?key=$KEY" \
      -H "Authorization: Bearer $LITELLM_MASTER_KEY"
    
    # switch a key off (and back on)
    curl -s https://llm.example.com/key/block \
      -H "Authorization: Bearer $LITELLM_MASTER_KEY" \
      -H "Content-Type: application/json" -d "{\"key\": \"$KEY\"}"
    curl -s https://llm.example.com/key/unblock \
      -H "Authorization: Bearer $LITELLM_MASTER_KEY" \
      -H "Content-Type: application/json" -d "{\"key\": \"$KEY\"}"

Before you hand out the first key

  • The master key never leaves your ops team — not in a laptop’s shell history, not in a shared doc.
  • Every key gets a budget and an expiry. There are no unlimited keys.
  • Budgets are hard limits: LiteLLM estimates a request’s cost before sending it and rejects it if the budget would be crossed. Turn on fail-closed budget enforcement so requests stop if spend can’t be checked.
  • The admin UI and management endpoints sit behind a VPN, tailnet or IP allow-list.
  • Prompts with personal data stay out of third-party logging (turn_off_message_logging).
  • Run Redis once you have more than one gateway instance, so rate limits and budgets are shared.
  • Pin the image version, back up Postgres, and keep config.yaml in version control.
  • Review spend by team every week for the first month — it shows you who actually uses what.

From production

What we learned running ours

Our gateway at llm.lintware.com has carried the AI traffic of our agents and the client systems we run since July 2026. These are the lessons that cost us something.

Stable model names saved us during a provider outage

When one provider’s credits ran out in September 2026, we pointed the model names our tools already used at a different provider. Every caller kept working without a single code change.

Don’t put a buffering proxy in front of streams

An edge worker that inspected traffic in front of our gateway cut off long streamed replies. We removed it in August 2026 and send traffic straight through a tunnel instead.

Test every modality through the gateway

One provider adapter quietly dropped images from requests. A one-pixel test image caught it — the model answered as if nothing was attached — and switching adapters fixed it.

Treat the model list as code

Our model catalogue lives in version control. Changes go through a review step, and we get a warning whenever a key still calls a model name we have retired.

Put voice through the same door

Speech-to-text and text-to-speech go through the same gateway, so voice features get the same keys, budgets and spend log as chat.

Give agents their own keys, too

Our AI agents reach models through the gateway with a virtual key each, so we can cap, audit or switch off any one agent without touching the others.

Questions

LiteLLM gateway questions

What is a LiteLLM gateway?

LiteLLM is an open-source proxy that sits between your people and AI providers. It exposes one OpenAI-compatible API, keeps the provider keys on the server, and gives each person or team a virtual key with its own allowed models, budget, rate limits and spend log.

Do LiteLLM budgets actually stop spending?

Yes. Budgets on keys, teams and team members are enforced: once a budget is crossed, requests are rejected. LiteLLM also estimates a request’s maximum cost before sending it, and can be set to fail closed if spend cannot be verified.

Can we use our Google Cloud, Azure or AWS credits behind LiteLLM?

Yes. LiteLLM routes to Vertex AI, Azure OpenAI and Amazon Bedrock as well as direct APIs. You can point different model names at different cloud projects — for example one Google Cloud project per department or course — so each group spends its own credits.

Can staff use chat apps, not just code?

Yes. Any tool that accepts an OpenAI-compatible endpoint works: give it the gateway URL and the person’s virtual key. Chat interfaces such as Open WebUI and LibreChat, SDKs, and many coding agents support this.

Is LiteLLM free?

The LiteLLM proxy is open source and free to self-host. Some advanced features — for example model-specific budgets — are part of LiteLLM Enterprise. You still pay your AI providers for usage.

How long does it take to set up?

A basic gateway can be running in an afternoon. A rollout for a whole organisation — teams, budgets, single sign-on for the admin side, monitoring and moving existing tools over — usually takes one to three weeks.

Can LintLabs set this up and run it for us?

Yes. We deploy and operate LiteLLM gateways — we have run our own in production since July 2026 for our agents and client systems. We connect your providers or cloud credits, set up teams and budgets, issue keys, and monitor it for you.