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.
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:
| Scope | Description |
|---|---|
organization | Organization-wide budget |
team | Budget for a specific team |
agent | Budget for an individual agent |
workflow | Budget for a workflow |
user | Budget 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]
}
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique budget identifier |
name | string | Yes | Human-readable budget name |
scope | string | Yes | Budget scope: organization, team, agent, workflow, user |
scope_id | string | No | ID of the scoped entity (required for team/agent/workflow/user scopes) |
limit_usd | number | Yes | Budget limit in USD |
period | string | Yes | Budget period: daily, weekly, monthly, quarterly, yearly |
on_exceed | string | Yes | Action when exceeded: warn, block, downgrade |
alert_thresholds | number[] | No | Percentage 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:
| Parameter | Type | Description |
|---|---|---|
scope | string | Filter by scope |
limit | integer | Maximum results (default: 50) |
offset | integer | Pagination 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:
| Parameter | Type | Description |
|---|---|---|
limit | integer | Maximum 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:
| Parameter | Type | Description |
|---|---|---|
period | string | Period: 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:
| Parameter | Type | Description |
|---|---|---|
group_by | string | Dimension: provider, model, agent, team, workflow |
period | string | Period: 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:
| Parameter | Type | Description |
|---|---|---|
limit | integer | Maximum records (default: 50) |
offset | integer | Pagination offset |
provider | string | Filter by provider |
model | string | Filter by model |
start_time | string | Filter by start time (ISO 8601) |
end_time | string | Filter 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:
| Parameter | Type | Description |
|---|---|---|
provider | string | Filter by provider |
model | string | Filter 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 Code | Error | Description |
|---|---|---|
| 400 | INVALID_BUDGET_CONFIG | Invalid budget configuration |
| 404 | BUDGET_NOT_FOUND | Budget not found |
| 409 | BUDGET_EXISTS | Budget with this ID already exists |
See Error Codes for the complete list.
Community vs Enterprise
| Feature | Community | Enterprise |
|---|---|---|
| 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 | ❌ | ✅ |