Documentation

Everything you need to route OpenAI, Claude, Groq, DeepSeek, or Llama API traffic through CostTrim. Every snippet below is pre-filled with your host — just swap in your key:

https://aicosttrim.com

Your CostTrim host — already filled in below. Don't have an account yet? Sign up free.

YOUR_API_KEY

A key from Dashboard → API Keys — this is your CostTrim key, not your OpenAI/Anthropic key (that goes in the Authorization header instead).

Quickstart

  1. Create a workspace (free, no card required).
  2. Generate a key in Dashboard → API Keys.
  3. Pick a path below: OpenAI, Claude, our SDK, the CLI, or the no-code widget.
  4. Send one request, then check Dashboard → Prompt Logs — it shows up within seconds.

OpenAI

Two options: call our proxy directly, or point the official openai package's baseURL at us and change nothing else in your code.

Option A — direct proxy call

cURL
curl -X POST https://aicosttrim.com/api/v1/monitor \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "X-API-KEY: YOUR_API_KEY" \
  -d '{
    "model": "gpt-4o-mini",
    "messages": [{"role": "user", "content": "Hello!"}],
    "metadata": { "userId": "usr_123" }
  }'
Python
import os, requests

response = requests.post(
    "https://aicosttrim.com/api/v1/monitor",
    headers={
        "Authorization": f"Bearer {os.environ['OPENAI_API_KEY']}",
        "X-API-KEY": "YOUR_API_KEY",
    },
    json={
        "model": "gpt-4o-mini",
        "messages": [{"role": "user", "content": "Hello!"}],
        "metadata": {"userId": "usr_123"},
    },
)
print(response.json()["choices"][0]["message"]["content"])
Node.js
const res = await fetch("https://aicosttrim.com/api/v1/monitor", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": `Bearer ${process.env.OPENAI_API_KEY}`,
    "X-API-KEY": "YOUR_API_KEY",
  },
  body: JSON.stringify({
    model: "gpt-4o-mini",
    messages: [{ role: "user", content: "Hello!" }],
    metadata: { userId: "usr_123" },
  }),
});
const data = await res.json();

Option B — zero code changes

Keep using the official SDK exactly as-is, just repoint it:

Node.js — official openai package
import OpenAI from "openai";

const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
  baseURL: "https://aicosttrim.com/api/openai/v1",
  defaultHeaders: { "X-API-KEY": "YOUR_API_KEY" },
});

// unchanged everywhere else in your code
const completion = await openai.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [{ role: "user", content: "Hello!" }],
});

Claude (Anthropic)

Same two options as OpenAI. One header difference — read the note below the snippets.

Option A — direct proxy call

cURL
curl -X POST https://aicosttrim.com/api/v1/monitor \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ANTHROPIC_API_KEY" \
  -H "X-API-KEY: YOUR_API_KEY" \
  -d '{
    "model": "claude-opus-5",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "Hello!"}],
    "metadata": { "userId": "usr_123" }
  }'
Python
import os, requests

response = requests.post(
    "https://aicosttrim.com/api/v1/monitor",
    headers={
        "Authorization": f"Bearer {os.environ['ANTHROPIC_API_KEY']}",
        "X-API-KEY": "YOUR_API_KEY",
    },
    json={
        "model": "claude-opus-5",
        "max_tokens": 1024,
        "messages": [{"role": "user", "content": "Hello!"}],
        "metadata": {"userId": "usr_123"},
    },
)
print(response.json()["content"][0]["text"])
Node.js
const res = await fetch("https://aicosttrim.com/api/v1/monitor", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": `Bearer ${process.env.ANTHROPIC_API_KEY}`,
    "X-API-KEY": "YOUR_API_KEY",
  },
  body: JSON.stringify({
    model: "claude-opus-5",
    max_tokens: 1024,
    messages: [{ role: "user", content: "Hello!" }],
    metadata: { userId: "usr_123" },
  }),
});
const data = await res.json();

Option B — zero code changes

Node.js — official @anthropic-ai/sdk package
import Anthropic from "@anthropic-ai/sdk";

const anthropic = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY,
  baseURL: "https://aicosttrim.com/api/anthropic",
  defaultHeaders: { "X-CostTrim-Key": "YOUR_API_KEY" },
});

// unchanged everywhere else in your code
const message = await anthropic.messages.create({
  model: "claude-opus-5",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Hello!" }],
});

Note: Option B for Claude uses X-CostTrim-Key, not X-API-KEY. The Anthropic SDK already sends your provider key via a header literally named x-api-key, so your CostTrim key needs a different header there to avoid colliding with it. Every other path (Option A, and OpenAI's Option B) uses X-API-KEY as normal.

Groq

Groq hosts open-weight models (Llama, Mixtral, Gemma, DeepSeek-distilled) at very low latency and cost. Point the official openai package's baseURL at our dedicated Groq route — it needs its own route (rather than the auto-detecting /api/v1/monitor) because Groq reuses other vendors' model names.

Node.js — official openai package
import OpenAI from "openai";

const groq = new OpenAI({
  apiKey: process.env.GROQ_API_KEY,
  baseURL: "https://aicosttrim.com/api/groq/v1",
  defaultHeaders: { "X-API-KEY": "YOUR_API_KEY" },
});

const completion = await groq.chat.completions.create({
  model: "llama-3.3-70b-versatile",
  messages: [{ role: "user", content: "Hello!" }],
});
cURL
curl -X POST https://aicosttrim.com/api/groq/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $GROQ_API_KEY" \
  -H "X-API-KEY: YOUR_API_KEY" \
  -d '{
    "model": "llama-3.3-70b-versatile",
    "messages": [{"role": "user", "content": "Hello!"}]
  }'

DeepSeek

DeepSeek's own API speaks the same format as OpenAI. Its model names (deepseek-chat, deepseek-reasoner) don't collide with anything else, so unlike Groq/Llama below, these also work on the auto-detecting /api/v1/monitor endpoint — a dedicated route is available too if you prefer repointing an existing SDK client.

Node.js — official openai package
import OpenAI from "openai";

const deepseek = new OpenAI({
  apiKey: process.env.DEEPSEEK_API_KEY,
  baseURL: "https://aicosttrim.com/api/deepseek/v1",
  defaultHeaders: { "X-API-KEY": "YOUR_API_KEY" },
});

const completion = await deepseek.chat.completions.create({
  model: "deepseek-chat",
  messages: [{ role: "user", content: "Hello!" }],
});
cURL
curl -X POST https://aicosttrim.com/api/deepseek/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $DEEPSEEK_API_KEY" \
  -H "X-API-KEY: YOUR_API_KEY" \
  -d '{
    "model": "deepseek-chat",
    "messages": [{"role": "user", "content": "Hello!"}]
  }'

Llama API

Meta's own hosted Llama API (api.llama.com), also OpenAI-compatible. Needs its own route — Groq serves Llama models too, under different pricing, so model names alone can't tell them apart.

Node.js — official openai package
import OpenAI from "openai";

const llama = new OpenAI({
  apiKey: process.env.LLAMA_API_KEY,
  baseURL: "https://aicosttrim.com/api/llama/v1",
  defaultHeaders: { "X-API-KEY": "YOUR_API_KEY" },
});

const completion = await llama.chat.completions.create({
  model: "Llama-3.3-70B-Instruct",
  messages: [{ role: "user", content: "Hello!" }],
});
cURL
curl -X POST https://aicosttrim.com/api/llama/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $LLAMA_API_KEY" \
  -H "X-API-KEY: YOUR_API_KEY" \
  -d '{
    "model": "Llama-3.3-70B-Instruct",
    "messages": [{"role": "user", "content": "Hello!"}]
  }'

Claude Code CLI

Track and hard-cap what Claude Code spends on your Anthropic account — per day, workspace-wide — without changing how you use it. Set three environment variables (or the equivalent in ~/.claude/settings.json) and every Claude Code session routes through CostTrim automatically.

Shell
export ANTHROPIC_BASE_URL="https://aicosttrim.com/api/anthropic"
export ANTHROPIC_API_KEY="sk-ant-..."          # your real Anthropic key — never stored, forwarded per-request
export ANTHROPIC_CUSTOM_HEADERS="X-CostTrim-Key: YOUR_API_KEY"

Or in ~/.claude/settings.json:

settings.json
{
  "env": {
    "ANTHROPIC_BASE_URL": "https://aicosttrim.com/api/anthropic",
    "ANTHROPIC_API_KEY": "sk-ant-...",
    "ANTHROPIC_CUSTOM_HEADERS": "X-CostTrim-Key: YOUR_API_KEY"
  }
}

That's it — run claude as normal. Dashboard → Prompt Logs shows every session tagged claude-code, grouped by session in Traces.

Daily budget kill-switch

Set a daily $ cap in Dashboard → Settings → Claude Code CLI budget protection. Once today's Claude Code spend hits it, further requests are rejected instantly — before Anthropic is ever called — with a clean, Claude-Code-compliant error your session will surface immediately:

Response (429)
{
  "type": "error",
  "error": {
    "type": "rate_limit_error",
    "message": "CostTrim: Claude Code budget threshold exceeded for today. Session halted to protect your credit card."
  }
}

This is separate from the per-user monthly threshold used elsewhere — Claude Code sessions are bursty and workspace-wide, not attributed to one end-user, so it gets its own daily, workspace-level cap. Resets at midnight.

Node SDK — ai-metric-sdk

A thin client mirroring both official SDKs, for either provider from one import:

Node.js
import { createAIMetricClient } from "ai-metric-sdk";

const ai = createAIMetricClient({
  apiKey: "YOUR_API_KEY",
  openaiApiKey: process.env.OPENAI_API_KEY,
  anthropicApiKey: process.env.ANTHROPIC_API_KEY,
  baseUrl: "https://aicosttrim.com",
});

await ai.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [{ role: "user", content: "Hello!" }],
  userId: "usr_123",
  sessionId: "task_9f2a", // optional — groups multi-step calls in Traces
});

await ai.messages.create({
  model: "claude-opus-5",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Hello!" }],
  userId: "usr_123",
});

See the package README for error handling, framework examples, and full API reference.

CLI — automatic migration

Already have new OpenAI(...) or new Anthropic(...) somewhere in your codebase? Have it wired up automatically:

Terminal
npx ai-metric init --base-url https://aicosttrim.com

Dry-run by default — shows exactly what it would change before writing anything. Finds every client constructor and injects baseURL/defaultHeaders, skipping anything it isn't confident about rather than guessing.

No code at all

Don't want to touch code? Dashboard → Chat Widget lets you paste your provider key into a form and get back an embeddable chat box — one <iframe> tag, nothing else.

Create a widget →

Python — FastAPI

Configure the OpenAI (or Anthropic) client once, at startup, and inject it wherever you need it — same pattern as any other FastAPI dependency.

app/dependencies.py
import os
from openai import OpenAI

def get_ai_client() -> OpenAI:
    return OpenAI(
        api_key=os.environ["OPENAI_API_KEY"],
        base_url="https://aicosttrim.com/api/openai/v1",
        default_headers={"X-API-KEY": os.environ["AI_METRIC_API_KEY"]},
    )
app/routers/chat.py
from fastapi import APIRouter, Depends
from openai import OpenAI
from app.dependencies import get_ai_client

router = APIRouter()

@router.post("/chat")
def chat(message: str, user_id: str, ai: OpenAI = Depends(get_ai_client)):
    completion = ai.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": message}],
        user=user_id,  # shows up as the attributed user in CostTrim
    )
    return {"reply": completion.choices[0].message.content}

Python — Django

Point the client at CostTrim once in settings.py, reuse it from any view.

settings.py
import os

AI_METRIC_CLIENT_CONFIG = {
    "api_key": os.environ["OPENAI_API_KEY"],
    "base_url": "https://aicosttrim.com/api/openai/v1",
    "default_headers": {"X-API-KEY": os.environ["AI_METRIC_API_KEY"]},
}
myapp/views.py
from django.conf import settings
from django.http import JsonResponse
from openai import OpenAI

client = OpenAI(**settings.AI_METRIC_CLIENT_CONFIG)

def chat_view(request):
    message = request.POST["message"]
    completion = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": message}],
        user=str(request.user.id),
    )
    return JsonResponse({"reply": completion.choices[0].message.content})

Telegram bot — python-telegram-bot

Every Telegram user's numeric ID becomes the attributed userId in CostTrim, so you get per-Telegram-user cost breakdown for free.

bot.py
import os
from telegram import Update
from telegram.ext import Application, MessageHandler, ContextTypes, filters
from openai import OpenAI

ai = OpenAI(
    api_key=os.environ["OPENAI_API_KEY"],
    base_url="https://aicosttrim.com/api/openai/v1",
    default_headers={"X-API-KEY": os.environ["AI_METRIC_API_KEY"]},
)

async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
    completion = ai.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": update.message.text}],
        user=f"tg_{update.effective_user.id}",
    )
    await update.message.reply_text(completion.choices[0].message.content)

app = Application.builder().token(os.environ["TELEGRAM_BOT_TOKEN"]).build()
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
app.run_polling()

Telegram bot — Telegraf

bot.js
import { Telegraf } from "telegraf";
import OpenAI from "openai";

const ai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
  baseURL: "https://aicosttrim.com/api/openai/v1",
  defaultHeaders: { "X-API-KEY": process.env.AI_METRIC_API_KEY },
});

const bot = new Telegraf(process.env.TELEGRAM_BOT_TOKEN);

bot.on("text", async (ctx) => {
  const completion = await ai.chat.completions.create({
    model: "gpt-4o-mini",
    messages: [{ role: "user", content: ctx.message.text }],
    user: `tg_${ctx.from.id}`,
  });
  await ctx.reply(completion.choices[0].message.content);
});

bot.launch();
Questions not covered here? See the FAQ, or create a workspace and try it directly.