← Code Recipes
Hosting, Gateways & Local

LiteLLM Free code examples in Python and JavaScript

A proxy that normalises a hundred providers to one API, with budgets and keys.

C# Python Java JavaScript

WHAT THIS PAGE COVERS

Per-team spend limits, which is the feature teams actually adopt it for.

Model fast
Package litellm
Checked

Model ids change. If a sample returns a 404 on the model, that is the first thing to check against the official docs.

Install

The proxy extra, and a Postgres instance. The database is not optional if you intend to enforce anything.

pip install 'litellm[proxy]'

docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=dev postgres:17

export LITELLM_MASTER_KEY="sk-master-dev"    # generate a long random one
export DATABASE_URL="postgresql://postgres:dev@localhost:5432/postgres"
The config

model_name is the alias callers ask for; litellm_params says what it really is. That indirection is the point — swapping a model for every caller is one line here and no change anywhere else.

# config.yaml
model_list:
  - model_name: fast                       # what callers request
    litellm_params:
      model: openai/gpt-5.4-mini           # what it actually is
      api_key: os.environ/OPENAI_API_KEY

  - model_name: smart
    litellm_params:
      model: anthropic/claude-sonnet-4.6
      api_key: os.environ/ANTHROPIC_API_KEY

general_settings:
  master_key: os.environ/LITELLM_MASTER_KEY
  database_url: os.environ/DATABASE_URL    # REQUIRED for budgets

litellm_settings:
  max_budget: 500                          # proxy-wide ceiling
  budget_duration: 30d
Teams and virtual keys

Provider keys stay in the proxy's environment. Everyone else gets a LiteLLM key with a budget and an allow-list — and revoking one is an API call rather than a rotation across every repository that had it.

litellm config.yaml

# A team with a monthly ceiling.
curl -sX POST 'http://localhost:4000/team/new' \
  -H "Authorization: Bearer $LITELLM_MASTER_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
        "team_alias": "search-squad",
        "max_budget": 100,
        "budget_duration": "30d",
        "rpm_limit": 99
      }'

# A key inside that team, with its own smaller budget and a
# restricted model list.
curl -sX POST 'http://localhost:4000/key/generate' \
  -H "Authorization: Bearer $LITELLM_MASTER_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
        "team_id": "<team-id-from-above>",
        "max_budget": 10,
        "budget_duration": "30d",
        "models": ["fast"]
      }'
Calling it

An OpenAI client against the proxy. The application never sees a provider key, and the model name is the alias from the config rather than a vendor's id.

import os
from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:4000",
    api_key=os.environ["LITELLM_VIRTUAL_KEY"],   # not the provider key
)

completion = client.chat.completions.create(
    model="fast",             # the alias, not openai/gpt-5.4-mini
    messages=[{"role": "user", "content": "Explain a database index."}],
)

print(completion.choices[0].message.content)
What happens when a budget runs out

The proxy returns 400 with a budget message — not 429, and not a silent downgrade. Handle it explicitly, because a retry loop written for rate limits will hammer a spent budget forever.

import openai

try:
    completion = client.chat.completions.create(
        model="fast",
        messages=[{"role": "user", "content": "Explain a database index."}],
    )
except openai.BadRequestError as error:
    message = str(error)

    # Budget exhaustion arrives as a 400, so generic 429 retry logic
    # will not catch it and generic 400 handling will call it a bug.
    if "budget" in message.lower():
        raise RuntimeError("Team budget exhausted — raise it or wait.") from error

    raise

# Check spend before it bites:
#   curl http://localhost:4000/key/info \
#     -H "Authorization: Bearer $LITELLM_VIRTUAL_KEY"
Install

The proxy is Python and runs as a service. Nothing LiteLLM-specific is installed in Node.

# On the proxy host:
#   pip install 'litellm[proxy]'
#   litellm config.yaml

npm install openai

export LITELLM_VIRTUAL_KEY="sk-..."          # from /key/generate
Calling it

The base URL is the proxy and the model is the alias. The provider key is not present in this process at all, which is the security argument for the whole arrangement.

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "http://localhost:4000",
  apiKey: process.env.LITELLM_VIRTUAL_KEY,   // not a provider key
});

const completion = await client.chat.completions.create({
  model: "fast",              // the alias from config.yaml
  messages: [{ role: "user", content: "Explain a database index." }],
});

console.log(completion.choices[0].message.content);
Attributing spend to something you can act on

Tags and a user id turn one aggregate bill into per-feature numbers. Without them the monthly figure is a single line item nobody can do anything about.

const completion = await client.chat.completions.create(
  {
    model: "fast",
    messages: [{ role: "user", content: "Explain a database index." }],
    // Rides along in the body; the proxy records it against the spend.
    user: "tenant-acme",
    metadata: {
      tags: ["feature:search", "env:production"],
    },
  },
  {
    // Or as headers, which survives a typed client that strips
    // unknown body fields.
    headers: { "x-litellm-tags": "feature:search,env:production" },
  },
);
Handling an exhausted budget

A spent budget is a 400 with a budget message, not a 429. Generic retry logic aimed at rate limits will retry it forever and get nowhere.

async function ask(messages) {
  try {
    return await client.chat.completions.create({ model: "fast", messages });
  } catch (error) {
    const message = String(error?.message ?? "");

    if (error?.status === 400 && /budget/i.test(message)) {
      // Not transient. Do not retry.
      throw new Error("Team budget exhausted — raise it or wait for the reset.");
    }

    throw error;
  }
}

// Current spend for this key:
//   GET http://localhost:4000/key/info
//   Authorization: Bearer $LITELLM_VIRTUAL_KEY

QUESTIONS

Which languages are the LiteLLM examples in?

Python and JavaScript. Every sample runs as pasted and reads its credentials from an environment variable — no key is ever written into the code.

Which package do I install for LiteLLM?

The samples use litellm. The install step on each language tab gives the exact command.

Which LiteLLM model do these examples use?

fast, checked against the official documentation on 26 September 2026. Model ids change often; if a call returns a model-not-found error, check the current list in the official docs.

Where is the official LiteLLM documentation?

https://docs.litellm.ai/ — it is linked at the bottom of this page, and it is the authority whenever it disagrees with a sample here.

ALSO IN HOSTING, GATEWAYS & LOCAL

The authority

Official LiteLLM documentation

Model names, pricing and rate limits change faster than any page here can. When this page and the official docs disagree, the official docs are right.

Read the docs ↗

https://docs.litellm.ai/

New drops, every week

Free tools & Claude templates, landing regularly.

We keep shipping new free tools, code recipes and Claude Code templates. Follow @freeyantra on Instagram or join the newsletter so you never miss one.

Follow @freeyantra

or get them by email

Double opt-in. Unsubscribe any time. Privacy