Skip to main content

Cost Controls API

The Cost Controls API provides budget management and LLM usage tracking capabilities, enabling organizations to set spending limits, receive alerts, and enforce budget policies on LLM usage.

SDK Support

All Cost Controls endpoints are available through the official SDKs:

Overview

Cost controls in AxonFlow are governance policies. Budget limits are enforced at multiple scopes:

ScopeDescription
organizationOrganization-wide budget
teamBudget for a specific team
agentBudget for an individual agent
workflowBudget for a workflow
userBudget for a specific user

Budget Management

Create Budget

Create a new budget with spending limits.

POST /api/v1/budgets

Headers:

Content-Type: application/json
X-Org-ID: your-org-id
X-Client-Secret: your-secret

Request Body:

{
"id": "monthly-budget",
"name": "Monthly Production Budget",
"scope": "organization",
"limit_usd": 1000.00,
"period": "monthly",
"on_exceed": "warn",
"alert_thresholds": [50, 80, 100]
}
FieldTypeRequiredDescription
idstringYesUnique budget identifier
namestringYesHuman-readable budget name
scopestringYesBudget scope: organization, team, agent, workflow, user
scope_idstringNoID of the scoped entity (required for team/agent/workflow/user scopes)
limit_usdnumberYesBudget limit in USD
periodstringYesBudget period: daily, weekly, monthly, quarterly, yearly
on_exceedstringYesAction when exceeded: warn, block, downgrade
alert_thresholdsnumber[]NoPercentage thresholds for alerts (e.g., [50, 80, 100])

Response (201 Created):

{
"id": "monthly-budget",
"name": "Monthly Production Budget",
"scope": "organization",
"limit_usd": 1000.00,
"period": "monthly",
"on_exceed": "warn",
"alert_thresholds": [50, 80, 100],
"enabled": true,
"created_at": "2026-01-04T00:00:00Z",
"updated_at": "2026-01-04T00:00:00Z"
}

List Budgets

List all budgets for the organization.

GET /api/v1/budgets

Query Parameters:

ParameterTypeDescription
scopestringFilter by scope
limitintegerMaximum results (default: 50)
offsetintegerPagination offset (default: 0)

Response:

{
"budgets": [
{
"id": "monthly-budget",
"name": "Monthly Production Budget",
"scope": "organization",
"limit_usd": 1000.00,
"period": "monthly",
"on_exceed": "warn",
"alert_thresholds": [50, 80, 100],
"enabled": true
}
],
"total": 1
}

Get Budget

Get a specific budget by ID.

GET /api/v1/budgets/{id}

Update Budget

Update an existing budget configuration.

PUT /api/v1/budgets/{id}

Request Body:

{
"name": "Updated Budget Name",
"limit_usd": 2000.00,
"on_exceed": "block",
"alert_thresholds": [25, 50, 75, 100]
}

All fields are optional. Only provided fields are updated.

Delete Budget

Delete a budget by ID.

DELETE /api/v1/budgets/{id}

Response: 204 No Content

Budget Status & Alerts

Get Budget Status

Get real-time status of a budget including current usage.

GET /api/v1/budgets/{id}/status

Response:

{
"budget": {
"id": "monthly-budget",
"name": "Monthly Production Budget",
"limit_usd": 1000.00,
"period": "monthly"
},
"used_usd": 450.25,
"remaining_usd": 549.75,
"percentage": 45.025,
"period_start": "2026-01-01T00:00:00Z",
"period_end": "2026-02-01T00:00:00Z",
"is_exceeded": false,
"is_blocked": false
}

Get Budget Alerts

Get alerts triggered for a specific budget.

GET /api/v1/budgets/{id}/alerts

Query Parameters:

ParameterTypeDescription
limitintegerMaximum alerts to return (default: 50)

Response:

{
"alerts": [
{
"id": "alert-123",
"budget_id": "monthly-budget",
"alert_type": "threshold",
"threshold": 50,
"percentage_reached": 52.3,
"amount_usd": 523.00,
"message": "Budget 'Monthly Production Budget' has reached 50% threshold",
"created_at": "2026-01-15T10:30:00Z"
}
],
"count": 1
}

Check Budget (Pre-flight)

Check if a request should be allowed based on budget constraints. Use this before making LLM requests.

POST /api/v1/budgets/check

Request Body:

{
"org_id": "your-org-id",
"team_id": "engineering",
"agent_id": "support-bot"
}

Response (Allowed):

{
"allowed": true
}

Response (Blocked):

{
"allowed": false,
"action": "block",
"budget_id": "team-budget",
"budget_name": "Engineering Team Budget",
"used_usd": 520.00,
"limit_usd": 500.00,
"percentage": 104.0,
"message": "Budget 'Engineering Team Budget' exceeded - requests blocked"
}

Usage Tracking

Get Usage Summary

Get aggregated LLM usage for the current period.

GET /api/v1/usage

Query Parameters:

ParameterTypeDescription
periodstringPeriod: daily, weekly, monthly, quarterly, yearly

Response:

{
"period": "monthly",
"period_start": "2026-01-01T00:00:00Z",
"period_end": "2026-02-01T00:00:00Z",
"total_cost_usd": 1523.45,
"total_requests": 45230,
"total_tokens_in": 12500000,
"total_tokens_out": 8750000,
"by_provider": {
"openai": {
"cost_usd": 890.00,
"requests": 25000,
"tokens_in": 7500000,
"tokens_out": 5000000
},
"anthropic": {
"cost_usd": 633.45,
"requests": 20230,
"tokens_in": 5000000,
"tokens_out": 3750000
}
}
}

Get Usage Breakdown

Get usage broken down by a specific dimension.

GET /api/v1/usage/breakdown

Query Parameters:

ParameterTypeDescription
group_bystringDimension: provider, model, agent, team, workflow
periodstringPeriod: daily, weekly, monthly, quarterly, yearly

Response:

{
"group_by": "model",
"period": "monthly",
"items": [
{
"name": "gpt-4-turbo",
"cost_usd": 650.00,
"requests": 8500,
"percentage": 42.7
},
{
"name": "claude-3-sonnet",
"cost_usd": 480.00,
"requests": 12000,
"percentage": 31.5
},
{
"name": "gpt-3.5-turbo",
"cost_usd": 120.00,
"requests": 18000,
"percentage": 7.9
}
],
"total_cost_usd": 1523.45
}

List Usage Records

Get detailed usage records with filtering.

GET /api/v1/usage/records

Query Parameters:

ParameterTypeDescription
limitintegerMaximum records (default: 50)
offsetintegerPagination offset
providerstringFilter by provider
modelstringFilter by model
start_timestringFilter by start time (ISO 8601)
end_timestringFilter by end time (ISO 8601)

Response:

{
"records": [
{
"id": "usage-123",
"timestamp": "2026-01-04T12:30:00Z",
"provider": "openai",
"model": "gpt-4-turbo",
"tokens_in": 1500,
"tokens_out": 800,
"cost_usd": 0.045,
"agent_id": "support-bot",
"team_id": "engineering",
"request_id": "req-abc123"
}
],
"total": 1
}

Pricing Information

Get Pricing

Get model pricing information.

GET /api/v1/pricing

Query Parameters:

ParameterTypeDescription
providerstringFilter by provider
modelstringFilter by model

Response:

{
"pricing": [
{
"provider": "openai",
"model": "gpt-4-turbo",
"input_price_per_1k": 0.01,
"output_price_per_1k": 0.03,
"currency": "USD",
"updated_at": "2026-01-01T00:00:00Z"
},
{
"provider": "anthropic",
"model": "claude-3-sonnet",
"input_price_per_1k": 0.003,
"output_price_per_1k": 0.015,
"currency": "USD",
"updated_at": "2026-01-01T00:00:00Z"
}
]
}

SDK Examples

Python

from axonflow import AxonFlow, CreateBudgetRequest, BudgetScope, BudgetPeriod, BudgetOnExceed

async with AxonFlow(endpoint="http://localhost:8081") as client:
# Create a budget
budget = await client.create_budget(CreateBudgetRequest(
id="team-budget",
name="Engineering Budget",
scope=BudgetScope.TEAM,
scope_id="engineering",
limit_usd=5000.0,
period=BudgetPeriod.MONTHLY,
on_exceed=BudgetOnExceed.WARN,
alert_thresholds=[50, 80, 100]
))

# Check budget before request
decision = await client.check_budget(BudgetCheckRequest(
team_id="engineering"
))

if decision.allowed:
# Proceed with LLM request
pass
else:
print(f"Request blocked: {decision.message}")

# Get usage summary
usage = await client.get_usage_summary(period="monthly")
print(f"Total cost: ${usage.total_cost_usd:.2f}")

TypeScript

import { AxonFlow, BudgetScope, BudgetPeriod, BudgetOnExceed } from '@axonflow/sdk';

const client = new AxonFlow({
endpoint: 'http://localhost:8081'
});

// Create a budget
const budget = await client.createBudget({
id: 'team-budget',
name: 'Engineering Budget',
scope: BudgetScope.TEAM,
scopeId: 'engineering',
limitUsd: 5000,
period: BudgetPeriod.MONTHLY,
onExceed: BudgetOnExceed.WARN,
alertThresholds: [50, 80, 100]
});

// Check budget before request
const decision = await client.checkBudget({
teamId: 'engineering'
});

if (decision.allowed) {
// Proceed with LLM request
} else {
console.log(`Request blocked: ${decision.message}`);
}

// Get usage breakdown
const breakdown = await client.getUsageBreakdown('model', 'monthly');
breakdown.items.forEach(item => {
console.log(`${item.name}: $${item.costUsd.toFixed(2)} (${item.percentage}%)`);
});

Go

package main

import (
"context"
"fmt"
axonflow "github.com/getaxonflow/axonflow-sdk-go"
)

func main() {
client, _ := axonflow.NewClient(axonflow.Config{
OrchestratorURL: "http://localhost:8081",
})
defer client.Close()

ctx := context.Background()

// Create a budget
budget, _ := client.CreateBudget(ctx, axonflow.CreateBudgetRequest{
ID: "team-budget",
Name: "Engineering Budget",
Scope: "team",
ScopeID: "engineering",
LimitUSD: 5000.0,
Period: "monthly",
OnExceed: "warn",
AlertThresholds: []int{50, 80, 100},
})
fmt.Printf("Created budget: %s\n", budget.ID)

// Check budget before request
decision, _ := client.CheckBudget(ctx, axonflow.CheckBudgetRequest{
TeamID: "engineering",
})

if decision.Allowed {
// Proceed with LLM request
} else {
fmt.Printf("Request blocked: %s\n", decision.Message)
}

// Get usage summary
usage, _ := client.GetUsageSummary(ctx, "monthly")
fmt.Printf("Total cost: $%.2f\n", usage.TotalCostUSD)
}

Java

import com.getaxonflow.sdk.AxonFlow;
import com.getaxonflow.sdk.AxonFlowConfig;
import com.getaxonflow.sdk.types.costcontrols.CostControlTypes.*;

public class CostControlsExample {
public static void main(String[] args) {
AxonFlowConfig config = AxonFlowConfig.builder()
.orchestratorUrl("http://localhost:8081")
.build();

try (AxonFlow client = AxonFlow.create(config)) {
// Create a budget
Budget budget = client.createBudget(CreateBudgetRequest.builder()
.id("team-budget")
.name("Engineering Budget")
.scope(BudgetScope.TEAM)
.scopeId("engineering")
.limitUsd(5000.0)
.period(BudgetPeriod.MONTHLY)
.onExceed(BudgetOnExceed.WARN)
.alertThresholds(List.of(50, 80, 100))
.build());

// Check budget before request
BudgetDecision decision = client.checkBudget(BudgetCheckRequest.builder()
.teamId("engineering")
.build());

if (decision.isAllowed()) {
// Proceed with LLM request
} else {
System.out.println("Request blocked: " + decision.getMessage());
}

// Get usage summary
UsageSummary usage = client.getUsageSummary("monthly");
System.out.printf("Total cost: $%.2f%n", usage.getTotalCostUsd());
}
}
}

Error Responses

Status CodeErrorDescription
400INVALID_BUDGET_CONFIGInvalid budget configuration
404BUDGET_NOT_FOUNDBudget not found
409BUDGET_EXISTSBudget with this ID already exists

See Error Codes for the complete list.

Community vs Enterprise

FeatureCommunityEnterprise
Usage tracking
Budget limits
Budget alerts
Pre-flight budget check
Budget hierarchy
Usage forecast
Usage export
Alert channels (Slack, email, webhook)
Auto-downgrade
Budget rollover
Cost dashboard