Back to blog
Tutorial·9 min read·1692 words

How to Build a Multi-Model Cost Dashboard with AI APIs: Complete Tutorial

Learn how to build a real-time cost dashboard that tracks AI spending across multiple providers, compares token usage between models, and alerts you when costs spike. Full code examples in Python and TypeScript.

How to Build a Multi-Model Cost Dashboard with AI APIs: Complete Tutorial — illustration

If you're running AI models in production, costs can spiral out of control fast. A single bug causing an infinite loop, a user sending unexpectedly long prompts, or a model generating verbose outputs can turn a $50/month bill into a $5,000/month nightmare.

The solution? A multi-model cost dashboard that tracks your AI spending in real time, compares costs across providers, and alerts you when something goes wrong. In this tutorial, we'll build one from scratch.

What We're Building

We'll create a cost dashboard that:

  • Tracks token usage and costs across multiple AI providers
  • Compares spending between models in real time
  • Shows cost trends over time with charts
  • Sends alerts when daily costs exceed a threshold
  • Recommends cheaper model alternatives

Prerequisites

  • Python 3.11+ or Node.js 20+
  • An API key from Qubax AI (or individual provider keys)
  • Basic familiarity with REST APIs

We'll use Python for this tutorial, but the concepts apply to any language.

Step 1: Set Up the Project

bash
mkdir ai-cost-dashboard && cd ai-cost-dashboard
python -m venv venv
source venv/bin/activate
pip install fastapi uvicorn httpx python-dotenv

Create a .env file with your API keys:

env
# Use Qubax AI as your unified gateway (recommended)
QUBAX_API_KEY=your_api_key_here
QUBAX_BASE_URL=https://api.qubax.ai/v1

# Or individual provider keys
OPENAI_API_KEY=your_openai_key
ANTHROPIC_API_KEY=your_anthropic_key
DEEPSEEK_API_KEY=your_deepseek_key

Using a unified gateway like Qubax AI is recommended because it gives you a single API endpoint for all models, unified billing, and built-in cost tracking.

Step 2: Create the Cost Tracker

First, let's build the core cost tracking module. This will log every API call with its token usage and calculated cost.

python
import httpx
import json
import sqlite3
from datetime import datetime, timedelta
from dataclasses import dataclass, asdict
from typing import Optional

@dataclass
class UsageRecord:
    timestamp: str
    model: str
    provider: str
    input_tokens: int
    output_tokens: int
    input_cost: float
    output_cost: float
    total_cost: float
    request_id: str

class CostTracker:
    def __init__(self, db_path="costs.db"):
        self.conn = sqlite3.connect(db_path)
        self._init_db()
        
        # Current pricing per million tokens (update regularly)
        self.pricing = {
            "gpt-5.6-sol": {"input": 0.90, "output": 5.40},
            "claude-opus-5": {"input": 1.50, "output": 7.50},
            "deepseek-v4-pro": {"input": 0.11, "output": 0.33},
            "glm-5.2": {"input": 0.03, "output": 0.09},
            "qwen-3.8-max": {"input": 1.09, "output": 3.26},
        }
    
    def _init_db(self):
        self.conn.execute("""
            CREATE TABLE IF NOT EXISTS usage (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                timestamp TEXT,
                model TEXT,
                provider TEXT,
                input_tokens INTEGER,
                output_tokens INTEGER,
                input_cost REAL,
                output_cost REAL,
                total_cost REAL,
                request_id TEXT
            )
        """)
        self.conn.commit()
    
    def record_usage(self, model: str, provider: str, 
                     input_tokens: int, output_tokens: int,
                     request_id: str = ""):
        prices = self.pricing.get(model, {"input": 0, "output": 0})
        input_cost = (input_tokens / 1_000_000) * prices["input"]
        output_cost = (output_tokens / 1_000_000) * prices["output"]
        total_cost = input_cost + output_cost
        
        record = UsageRecord(
            timestamp=datetime.utcnow().isoformat(),
            model=model,
            provider=provider,
            input_tokens=input_tokens,
            output_tokens=output_tokens,
            input_cost=input_cost,
            output_cost=output_cost,
            total_cost=total_cost,
            request_id=request_id
        )
        
        self.conn.execute(
            "INSERT INTO usage VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
            (record.timestamp, record.model, record.provider,
             record.input_tokens, record.output_tokens,
             record.input_cost, record.output_cost,
             record.total_cost, record.request_id)
        )
        self.conn.commit()
        return record

Step 3: Build the API Client Wrapper

Next, let's create a wrapper that intercepts API calls, tracks usage, and logs costs automatically:

python
import os
from dotenv import load_dotenv

load_dotenv()

class AIClient:
    def __init__(self, tracker: CostTracker):
        self.tracker = tracker
        self.client = httpx.Client(
            base_url=os.getenv("QUBAX_BASE_URL", "https://api.qubax.ai/v1"),
            headers={"Authorization": f"Bearer {os.getenv('QUBAX_API_KEY')}"}
        )
    
    async def chat(self, model: str, messages: list, **kwargs):
        """Send a chat completion request and track costs."""
        response = self.client.post("/chat/completions", json={
            "model": model,
            "messages": messages,
            **kwargs
        })
        data = response.json()
        
        # Track usage
        usage = data.get("usage", {})
        self.tracker.record_usage(
            model=model,
            provider=self._get_provider(model),
            input_tokens=usage.get("prompt_tokens", 0),
            output_tokens=usage.get("completion_tokens", 0),
            request_id=data.get("id", "")
        )
        
        return data
    
    def _get_provider(self, model: str) -> str:
        provider_map = {
            "gpt": "OpenAI",
            "claude": "Anthropic",
            "deepseek": "DeepSeek",
            "glm": "Zhipu AI",
            "qwen": "Alibaba",
        }
        for prefix, provider in provider_map.items():
            if model.startswith(prefix):
                return provider
        return "Unknown"

Step 4: Create the Dashboard API

Now let's build a FastAPI server that serves cost analytics:

python
from fastapi import FastAPI, Query
from typing import Optional
import sqlite3
from datetime import datetime, timedelta

app = FastAPI(title="AI Cost Dashboard API")
tracker = CostTracker()

@app.get("/api/costs/summary")
def get_cost_summary(days: int = 7):
    """Get cost summary for the last N days."""
    since = (datetime.utcnow() - timedelta(days=days)).isoformat()
    
    conn = sqlite3.connect("costs.db")
    rows = conn.execute("""
        SELECT 
            model,
            provider,
            SUM(input_tokens) as total_input,
            SUM(output_tokens) as total_output,
            SUM(total_cost) as total_cost,
            COUNT(*) as request_count
        FROM usage 
        WHERE timestamp >= ?
        GROUP BY model, provider
        ORDER BY total_cost DESC
    """, (since,)).fetchall()
    
    models = []
    grand_total = 0
    for row in rows:
        model, provider, inp, out, cost, count = row
        models.append({
            "model": model,
            "provider": provider,
            "input_tokens": inp,
            "output_tokens": out,
            "total_cost": round(cost, 4),
            "request_count": count,
            "avg_cost_per_request": round(cost / count, 6) if count else 0
        })
        grand_total += cost
    
    return {
        "period_days": days,
        "total_cost": round(grand_total, 4),
        "model_count": len(models),
        "models": models
    }

@app.get("/api/costs/daily")
def get_daily_costs(days: int = 30):
    """Get daily cost breakdown."""
    since = (datetime.utcnow() - timedelta(days=days)).isoformat()
    
    conn = sqlite3.connect("costs.db")
    rows = conn.execute("""
        SELECT 
            DATE(timestamp) as date,
            model,
            SUM(total_cost) as daily_cost,
            COUNT(*) as request_count
        FROM usage 
        WHERE timestamp >= ?
        GROUP BY DATE(timestamp), model
        ORDER BY date DESC
    """, (since,)).fetchall()
    
    daily = {}
    for row in rows:
        date, model, cost, count = row
        if date not in daily:
            daily[date] = {"date": date, "total": 0, "models": {}}
        daily[date]["total"] += cost
        daily[date]["models"][model] = round(cost, 4)
    
    return list(daily.values())

@app.get("/api/costs/alerts")
def get_cost_alerts(threshold: float = 10.0):
    """Check if any day exceeded the cost threshold."""
    conn = sqlite3.connect("costs.db")
    rows = conn.execute("""
        SELECT 
            DATE(timestamp) as date,
            SUM(total_cost) as daily_cost
        FROM usage 
        WHERE timestamp >= DATE('now', '-7 days')
        GROUP BY DATE(timestamp)
        HAVING daily_cost > ?
        ORDER BY daily_cost DESC
    """, (threshold,)).fetchall()
    
    alerts = []
    for row in rows:
        date, cost = row
        alerts.append({
            "date": date,
            "cost": round(cost, 2),
            "threshold": threshold,
            "message": "Daily cost exceeded threshold"
        })
    
    return {"alerts": alerts}

Step 5: Add Model Recommendation Engine

One of the most powerful features of a cost dashboard is suggesting cheaper alternatives:

python
@app.get("/api/recommendations")
def get_recommendations():
    """Recommend cheaper model alternatives based on usage."""
    conn = sqlite3.connect("costs.db")
    rows = conn.execute("""
        SELECT model, SUM(total_cost) as total_cost, COUNT(*) as count
        FROM usage 
        WHERE timestamp >= DATE('now', '-7 days')
        GROUP BY model
    """).fetchall()
    
    # Define cheaper alternatives
    alternatives = {
        "gpt-5.6-sol": ["deepseek-v4-pro", "glm-5.2"],
        "claude-opus-5": ["deepseek-v4-pro", "glm-5.2"],
        "qwen-3.8-max": ["deepseek-v4-pro", "glm-5.2"],
    }
    
    recommendations = []
    for row in rows:
        model, cost, count = row
        if model in alternatives:
            for alt in alternatives[model]:
                alt_price = tracker.pricing.get(alt, {})
                orig_price = tracker.pricing.get(model, {})
                
                if alt_price and orig_price:
                    savings = cost * (1 - (alt_price["input"] + alt_price["output"]) / 
                                      (orig_price["input"] + orig_price["output"]))
                    recommendations.append({
                        "current_model": model,
                        "suggested_model": alt,
                        "current_weekly_cost": round(cost, 2),
                        "estimated_weekly_cost": round(cost - savings, 2),
                        "estimated_savings": round(savings, 2),
                        "savings_percent": round((savings / cost) * 100, 1)
                    })
    
    return {"recommendations": recommendations}

Step 6: Run the Dashboard

bash
uvicorn main:app --reload --port 8000

Now you can query your dashboard:

bash
# Get 7-day cost summary
curl http://localhost:8000/api/costs/summary?days=7

# Get daily breakdown
curl http://localhost:8000/api/costs/daily?days=30

# Check for cost alerts
curl http://localhost:8000/api/costs/alerts?threshold=10

# Get model recommendations
curl http://localhost:8000/api/recommendations

Step 7: Add Real-Time Monitoring

For production use, add a background task that checks costs every hour and sends alerts:

python
import asyncio
import smtplib
from email.mime.text import MIMEText

async def monitor_costs():
    """Background task to monitor costs and send alerts."""
    while True:
        conn = sqlite3.connect("costs.db")
        
        # Check today's cost
        today = datetime.utcnow().strftime("%Y-%m-%d")
        row = conn.execute("""
            SELECT SUM(total_cost) FROM usage 
            WHERE DATE(timestamp) = ?
        """, (today,)).fetchone()
        
        today_cost = row[0] or 0
        
        if today_cost > 50:  # $50 daily threshold
            send_alert_email(
                subject="AI Cost Alert",
                body="Daily AI cost has exceeded threshold. Check dashboard."
            )
        
        await asyncio.sleep(3600)  # Check every hour

def send_alert_email(subject: str, body: str):
    msg = MIMEText(body)
    msg["Subject"] = subject
    msg["From"] = "[email protected]"
    msg["To"] = "[email protected]"
    
    with smtplib.SMTP("smtp.yourcompany.com") as server:
        server.send_message(msg)

Production Tips

  1. Use a real database: Replace SQLite with PostgreSQL for production. SQLite works fine for prototyping but won't handle concurrent writes at scale.
  1. Add authentication: Protect your dashboard API with API keys or OAuth.
  1. Use a unified gateway: Instead of managing separate API keys for each provider, use Qubax AI which provides a single OpenAI-compatible endpoint for all models with built-in cost tracking.
  1. Set up automated cost routing: Once you have cost data, automatically route simple queries to cheaper models. For example, use GLM 5.2 ($0.03/M input) for basic tasks and reserve GPT-5.6 Sol ($0.90/M input) for complex reasoning.
  1. Implement prompt caching: Cache responses for identical queries to avoid paying for the same computation twice.
  1. Track per-user costs: Extend the schema to track which user or feature generated each cost, so you can identify which parts of your application are most expensive.

Full Code Structure

code
ai-cost-dashboard/
├── .env
├── main.py              # FastAPI server
├── tracker.py           # CostTracker and AIClient
├── monitor.py           # Background monitoring task
├── requirements.txt
└── costs.db             # SQLite database (auto-created)

FAQ

What is an AI cost dashboard?

An AI cost dashboard is a tool that tracks how much you're spending on AI API calls across different models and providers. It shows token usage, calculates costs, identifies trends, and alerts you when spending exceeds thresholds.

Why do I need to track AI costs?

AI costs can spiral quickly. A single bug, a user sending long prompts, or a model generating verbose responses can multiply your costs. Without monitoring, you might not notice until you get a surprisingly large bill.

How do I calculate AI API costs?

AI API costs = (input tokens × input price / 1,000,000) + (output tokens × output price / 1,000,000). Prices are typically quoted per million tokens. For example, 500,000 input tokens at $1.00/M = $0.50.

Can I use one API for all AI models?

Yes! Using a unified gateway like Qubax AI gives you a single OpenAI-compatible API endpoint for hundreds of models from OpenAI, Anthropic, DeepSeek, Google, and more, with unified billing and cost tracking.

How can I reduce my AI API spending?

Route simple queries to cheaper models (like GLM 5.2 at $0.03/M input), implement prompt caching, optimize your prompts to use fewer tokens, test different effort settings, and set up cost alerts to catch spikes early.

What's the cheapest AI model for API calls?

GLM 5.2 from Zhipu AI is one of the cheapest capable models at $0.03 per million input tokens and $0.09 per million output tokens. DeepSeek V4 Pro is another budget option at $0.11/$0.33. Compare current prices at qubax.ai/models.

Article tags

#AI API#cost dashboard#Python#FastAPI#cost tracking
Share:Post on XTelegramLinkedInYHacker NewsReddit
Qubax AI

Qubax AI

AI Models at up to 99% off · Pay with crypto

Access GPT, Claude, Gemini, GLM & 340+ models through one OpenAI-compatible API. Up to 99% off. Pay with 200+ cryptocurrencies. No credit card needed.

Related articles