Skip to main content
Lesson 11 of 14 · Management API: Keys & Billing

Balance and automatic top-ups

Lesson 11 of 14 Updated July 29, 2026 Developer
On this page
  1. Monitor and automate top-ups
  2. Check balance details
  3. Automatic top-up system
  4. Consumption forecasting
  5. Integrated tracking dashboard
  6. Key takeaways

Monitor and automate top-ups

Combining prepaid balance tracking with usage analytics lets you set up a smart top-up system. Instead of topping up manually, you can automate the process based on thresholds and consumption forecasts.

Check balance details

The endpoint returns two things you shouldn’t confuse: the instant balance and the transaction history. The first answers “Can I still call the API?”, the second answers “How fast am I consuming?”. The second is what lets you anticipate, and therefore the only one you can base automation on.

curl "https://management-api.x.ai/v1/billing/teams/$TEAM_ID/prepaid/balance" \
  -H "Authorization: Bearer $MANAGEMENT_API_KEY"

The response contains the current balance and the transaction history (purchases and consumption).

Automatic top-up system

A well-configured automatic top-up relies on two numbers, and one of them is often forgotten. The trigger threshold must cover your consumption during the reaction time: if you check once a day, you need at least one day of credit in advance, otherwise automation will trigger after the cutoff. The monthly cap is the safeguard most often missing—without it, a faulty loop in your application can trigger top-up after top-up, and xAI credits are non-refundable.

These two values aren’t set arbitrarily: the next section shows how to calculate them based on your actual consumption.

import requests
from datetime import datetime, timedelta

MANAGEMENT_API = "https://management-api.x.ai"
MGMT_KEY = "xai-mgmt-..."
TEAM_ID = "team-..."

# Configuration
MIN_BALANCE = 50.00      # Top-up threshold
TOP_UP_AMOUNT = 200.00   # Top-up amount
MAX_MONTHLY = 1000.00    # Monthly cap

def get_balance():
    """Get the current prepaid balance."""
    resp = requests.get(
        f"{MANAGEMENT_API}/v1/billing/teams/{TEAM_ID}/prepaid/balance",
        headers={"Authorization": f"Bearer {MGMT_KEY}"}
    )
    return resp.json().get("balance", 0)

def get_monthly_top_ups():
    """Calculate the total top-ups for the current month."""
    resp = requests.get(
        f"{MANAGEMENT_API}/v1/billing/teams/{TEAM_ID}/prepaid/balance",
        headers={"Authorization": f"Bearer {MGMT_KEY}"}
    )
    # Filter transactions for the current month
    transactions = resp.json().get("transactions", [])
    current_month = datetime.now().strftime("%Y-%m")
    monthly_total = sum(
        t.get("amount", 0)
        for t in transactions
        if t.get("type") == "top-up" and t.get("date", "").startswith(current_month)
    )
    return monthly_total

def top_up(amount):
    """Perform a top-up."""
    resp = requests.post(
        f"{MANAGEMENT_API}/v1/billing/teams/{TEAM_ID}/prepaid/top-up",
        headers={
            "Authorization": f"Bearer {MGMT_KEY}",
            "Content-Type": "application/json"
        },
        json={"amount": amount}
    )
    return resp.status_code == 200

# Top-up logic
balance = get_balance()
monthly_spent = get_monthly_top_ups()

if balance < MIN_BALANCE:
    remaining_budget = MAX_MONTHLY - monthly_spent
    if remaining_budget >= TOP_UP_AMOUNT:
        if top_up(TOP_UP_AMOUNT):
            print(f"Top-up of ${TOP_UP_AMOUNT:.2f}. Estimated new balance: ${balance + TOP_UP_AMOUNT:.2f}")
        else:
            print("Error during top-up")
    else:
        print(f"Monthly cap reached (${monthly_spent:.2f} / ${MAX_MONTHLY:.2f})")
else:
    print(f"Sufficient balance: ${balance:.2f}")

Consumption forecasting

Forecasting turns monitoring into anticipation. A seven-day average is enough for most use cases; it gives you an exhaustion date, so you have time to act. Just beware of your own traffic seasonality—an average calculated over a slow week promises autonomy that will vanish once traffic picks up.

import requests
from datetime import datetime, timedelta

MANAGEMENT_API = "https://management-api.x.ai"
MGMT_KEY = "xai-mgmt-..."
TEAM_ID = "team-..."

# Consumption over the last 7 days
end = datetime.now()
start = end - timedelta(days=7)

usage_resp = requests.post(
    f"{MANAGEMENT_API}/v1/billing/teams/{TEAM_ID}/usage",
    headers={
        "Authorization": f"Bearer {MGMT_KEY}",
        "Content-Type": "application/json"
    },
    json={
        "analyticsRequest": {
            "timeRange": {
                "startTime": start.strftime("%Y-%m-%d %H:%M:%S"),
                "endTime": end.strftime("%Y-%m-%d %H:%M:%S"),
                "timezone": "Europe/Paris"
            },
            "timeUnit": "DAY",
            "values": [{"name": "cost", "aggregation": "SUM"}]
        }
    }
)

# Calculate daily average
data_points = usage_resp.json().get("dataPoints", [])
daily_costs = [p.get("value", 0) for p in data_points]
avg_daily_cost = sum(daily_costs) / len(daily_costs) if daily_costs else 0

# Estimate remaining days
balance_resp = requests.get(
    f"{MANAGEMENT_API}/v1/billing/teams/{TEAM_ID}/prepaid/balance",
    headers={"Authorization": f"Bearer {MGMT_KEY}"}
)
current_balance = balance_resp.json().get("balance", 0)

if avg_daily_cost > 0:
    days_remaining = current_balance / avg_daily_cost
    exhaustion_date = datetime.now() + timedelta(days=days_remaining)
    print(f"Average consumption: ${avg_daily_cost:.2f}/day")
    print(f"Current balance: ${current_balance:.2f}")
    print(f"Estimated exhaustion: {exhaustion_date.strftime('%m/%d/%Y')} ({days_remaining:.0f} days)")

Integrated tracking dashboard

The dashboard brings together what three different endpoints know about your costs: the prepaid balance, monthly billing charges, and configured limits. Separated, each tells an incomplete story—a comfortable balance says nothing about postpaid consumption running in parallel. It’s the reconciliation that gives the true cost of the current month.

#!/bin/bash
echo "=== xAI Dashboard - $(date '+%m/%d/%Y %H:%M') ==="

# Prepaid balance
BALANCE=$(curl -s "https://management-api.x.ai/v1/billing/teams/$TEAM_ID/prepaid/balance" \
  -H "Authorization: Bearer $MANAGEMENT_API_KEY" | python3 -c "import sys,json; print(json.load(sys.stdin).get('balance', 'N/A'))")
echo "Prepaid balance: \$${BALANCE}"

# Postpaid charges
POSTPAID=$(curl -s "https://management-api.x.ai/v1/billing/teams/$TEAM_ID/postpaid/invoice/preview" \
  -H "Authorization: Bearer $MANAGEMENT_API_KEY" | python3 -c "import sys,json; print(json.load(sys.stdin).get('totalAmount', 'N/A'))")
echo "Postpaid charges: \$${POSTPAID}"

# Spending limit
LIMIT=$(curl -s "https://management-api.x.ai/v1/billing/teams/$TEAM_ID/postpaid/spending-limits" \
  -H "Authorization: Bearer $MANAGEMENT_API_KEY" | python3 -c "import sys,json; print(json.load(sys.stdin).get('monthlyLimit', 'N/A'))")
echo "Monthly limit: \$${LIMIT}"

Key takeaways

  • Automate top-ups with a minimum threshold and a monthly cap
  • Use analytics to forecast credit exhaustion dates
  • Combine prepaid balance, postpaid charges, and limits in a unified dashboard
  • Credits are non-refundable—calibrate automatic top-ups with caution
  • Integrate these scripts into your cron or CI/CD pipeline