Cost & Budget
Colony Cloud is the consolidated home for cost observability and budgeting across your pipeline. This page documents the four reporting surfaces — cost summary, spend timeseries, model spend share, and budget overview — and the API endpoints that power them. For the underlying model (how spend is measured, what each budget control enforces, and what projection figures assume), see Cost & Budget concepts.
Cost summary
Section titled “Cost summary”Endpoint: GET /pipeline/cost-summary
The cost summary returns total LLM spend across four fixed horizons in a single query, so the KPI toggle on the Pipeline and Insights dashboards responds instantly without a new network round trip.
| Field | Horizon | SQL condition |
|---|---|---|
last24hUsd | Last 24 hours | recorded_at >= NOW() - INTERVAL '24 hours' |
last7dUsd | Last 7 days | recorded_at >= NOW() - INTERVAL '7 days' |
last30dUsd | Last 30 days | recorded_at >= NOW() - INTERVAL '30 days' |
lifetimeUsd | All time | Unfiltered SUM(cost_usd) |
All four values are summed from v1_cost_events.cost_usd in a single conditional-aggregate query — no separate requests per horizon.
Optional repo filter: Pass repo=owner/name to scope all four horizons to a single repository. The value must be in owner/name format; any other format returns a 422 with error code INVALID_INPUT.
Cost timeseries
Section titled “Cost timeseries”Endpoint: GET /pipeline/cost-timeseries
The cost timeseries buckets LLM spend into time intervals for charting. Missing intervals are zero-filled via generate_series so the chart always has continuous bars even for periods with no activity.
Parameters
Section titled “Parameters”| Parameter | Required | Values | Default |
|---|---|---|---|
granularity | Yes | hour, day, week, month | — |
from | No | ISO 8601 timestamp | 30 days before now |
to | No | ISO 8601 timestamp | Now |
repo | No | owner/name | All repos |
from must be before to. If either value is provided but is not a valid ISO 8601 timestamp, the endpoint returns 422 with error code INVALID_FROM or INVALID_TO respectively.
Bucket count limit
Section titled “Bucket count limit”To protect the database from unbounded queries, the endpoint estimates the number of buckets the requested range would produce and rejects requests that exceed 500 buckets (MAX_COST_TIMESERIES_BUCKETS) with a 422 and error code TOO_MANY_BUCKETS.
The estimate uses these fixed millisecond widths per granularity:
| Granularity | Milliseconds per bucket |
|---|---|
hour | 3,600,000 |
day | 86,400,000 |
week | 604,800,000 |
month | 2,592,000,000 |
Estimated bucket count = ceil((to − from) / msPerBucket). To avoid the limit, narrow the date range or choose a coarser granularity. For example, a 500-day range at day granularity would exceed the cap; switch to week or narrow to under 500 days.
Response
Section titled “Response”{ "granularity": "day", "buckets": [ { "periodStart": "2026-06-01T00:00:00.000Z", "costUsd": 1.42 }, { "periodStart": "2026-06-02T00:00:00.000Z", "costUsd": 0.00 }, ... ]}Each bucket’s periodStart is the UTC-truncated start of the interval at the requested granularity. Zero-cost buckets appear explicitly so chart rendering does not need gap-filling logic.
Model spend share and efficiency signals
Section titled “Model spend share and efficiency signals”Endpoint: GET /pipeline/cost-by-model
This endpoint returns per-model LLM spend and efficiency signals for a rolling window. It is the data source for the Cost & Efficiency table on the Insights dashboard — refer to that page for interpretation guidance on each metric.
Parameters
Section titled “Parameters”| Parameter | Required | Values |
|---|---|---|
window | Yes | 7d, 30d |
Response fields per model
Section titled “Response fields per model”| Field | Type | Description |
|---|---|---|
model | string | Model identifier, or (unknown) when the model field is absent |
totalCostUsd | number | Total LLM spend attributed to this model in the window |
issueCount | number | Distinct issues involving this model |
invocationCount | number | Total agent invocations for this model |
maxTurnsRate | number | null | Fraction of invocations that hit the agent turn limit (max_turns_count / invocationCount); null when invocationCount is 0 |
noProgressRate | number | null | Fraction of invocations that produced no meaningful code progress (no_progress_count / invocationCount); null when invocationCount is 0 |
Model spend share (the fraction of total org spend attributable to each model) is derived client-side by dividing each model’s totalCostUsd by the sum across all models.
The query uses a FULL OUTER JOIN between cost_events (spend attribution) and execution_telemetry (model metadata), so models that appear in only one table are still included in the response. Results are ordered by totalCostUsd descending.
Budget overview
Section titled “Budget overview”Endpoint: GET /pipeline/budget-overview
The budget overview provides org-level burn-rate reporting derived from the aggregate of per-repo budget_cap_usd values. It surfaces on the Pipeline Live view and is available per-tenant in Billing.
Response fields
Section titled “Response fields”| Field | Type | Description |
|---|---|---|
monthlyLimitUsd | number | null | Sum of budget_cap_usd across all repos whose repo_configs record has a non-NULL cap. null if no repository in the org has a cap set. |
spentUsd | number | Current UTC-month spend — sum of cost_usd from v1_cost_events since date_trunc('month', NOW() AT TIME ZONE 'UTC') |
todaySpentUsd | number | Current UTC-day spend — sum of cost_usd since date_trunc('day', NOW() AT TIME ZONE 'UTC') |
dailyLimitUsd | number | null | monthlyLimitUsd ÷ days in current UTC month; null when no cap is set |
remainingUsd | number | null | max(0, monthlyLimitUsd − spentUsd); null when no cap is set |
burnRateUsdPerDay | number | 7-day trailing spend divided by days elapsed in that window, with a floor of 1 day (so a very recent org always has a defined burn rate) |
projectedExhaustionDate | string | null | ISO 8601 date (YYYY-MM-DD) of projected budget exhaustion — calculated as today + ceil(remainingUsd / burnRateUsdPerDay) when the budget is not yet exhausted and burnRateUsdPerDay > 0; null otherwise |
isExhausted | boolean | true when spentUsd >= monthlyLimitUsd |
Burn rate floor
Section titled “Burn rate floor”The burn rate uses GREATEST(elapsed_days, 1.0) as the denominator, where elapsed_days is derived from EXTRACT(EPOCH FROM (NOW() − windowStart)) / 86400. This avoids division-by-zero at the very start of the 7-day window without rounding elapsed time up to a full day — elapsed time may be a fractional value above 1.
Projected exhaustion date
Section titled “Projected exhaustion date”projectedExhaustionDate is only populated when all three conditions hold: the budget has not already been exhausted (isExhausted = false), there is remaining budget (remainingUsd > 0), and the trailing burn rate is positive (burnRateUsdPerDay > 0). An org with no active spend returns null for this field regardless of the remaining budget.
Monthly cost projection
Section titled “Monthly cost projection”Endpoint: GET /pipeline/cost-projection
The monthly cost projection estimates future LLM spend by combining per-tier historical cost data with operator-supplied throughput and complexity mix assumptions. It is the data source for the Monthly Cost Projection panel on the Insights dashboard.
Parameters
Section titled “Parameters”| Parameter | Required | Format | Default |
|---|---|---|---|
throughputPerDay | Yes | Positive number | — |
mix | No | small/medium/large as slash-separated integers summing to 100 | 60/30/10 |
mix must be three slash-separated integers (e.g. 60/30/10) that sum to exactly 100. Any other format or non-integer values return a 422 with error code INVALID_INPUT.
Projection formula
Section titled “Projection formula”For each complexity tier, the projected monthly cost is:
projectedMonthlyUsd = avgCostUsd × (mixPercent / 100) × throughputPerDay × 30avgCostUsd is the historical average cost per completed issue of that tier, derived from v1_cost_events joined to pipeline_issues.complexity for issues with state = 'done' and a non-null complexity.
The low band substitutes the P25 per-issue cost for the average; when P25 is unavailable (insufficient samples for the tier), the low band contribution for that tier is 0. The high band substitutes the P75 per-issue cost; when P75 is unavailable, the high band falls back to avgCostUsd. Total projected figures are the sum across all three tiers.
Per-tier response fields
Section titled “Per-tier response fields”| Field | Type | Description |
|---|---|---|
complexity | string | small, medium, or large |
avgCostUsd | number | Historical average cost per completed issue of this tier |
p25CostUsd | number | null | P25 per-issue cost; null when the tier has insufficient sample data |
p75CostUsd | number | null | P75 per-issue cost; null when the tier has insufficient sample data |
sampleSize | number | Completed issues informing this tier’s statistics |
projectedMonthlyUsd | number | avgCostUsd × mixFraction × throughputPerDay × 30 |
Top-level response fields
Section titled “Top-level response fields”| Field | Type | Description |
|---|---|---|
throughputPerDay | number | The throughputPerDay input echoed back |
mix | object | The resolved mix ({ small, medium, large }) echoed back |
tiers | array | Per-tier entries in the order small, medium, large |
totalProjectedMonthlyUsd | number | Sum of projectedMonthlyUsd across all tiers |
lowBandMonthlyUsd | number | Sum of per-tier low-band figures (P25-based; tiers with null P25 contribute 0) |
highBandMonthlyUsd | number | Sum of per-tier high-band figures (P75-based; tiers with null P75 fall back to avgCostUsd) |
sampleSize | number | Total completed issues across all three tiers |
Assumptions and their limits
Section titled “Assumptions and their limits”The projection assumes future issues resemble historical ones per tier in both scope and cost. When a tier has a thin sample, the per-tier average and percentile bands may reflect an unrepresentative set of past issues. The throughput and mix are operator-supplied — Colony does not infer them from current pipeline state. The 30-day horizon is a fixed multiplier and does not account for planned pauses, team capacity changes, or calendar effects.
For a full explanation of what the projection figures assume and why they are approximate, see Cost & Budget concepts — Monthly cost projection.
The colony estimate CLI command provides a config-based variant of this projection for Self-Host operators:
colony estimate --throughput 8 --mix 50/35/15It accepts the same throughput and mix inputs and reads model routing from colony.config.yaml to estimate monthly spend without an API call.
Per-issue estimate
Section titled “Per-issue estimate”Endpoint: POST /pipeline/repos/:owner/:repo/estimate
The per-issue estimate returns a cost range for a single new issue before it is filed, based on a description and optional complexity hint. It blends repo-local history with a cross-tenant global baseline to handle repos with few completed issues.
Request body
Section titled “Request body”| Field | Required | Type | Description |
|---|---|---|---|
description | Yes | string | Issue description used to scope the estimate |
complexity | No | small | medium | large | Complexity hint; when provided, percentiles and success rate are filtered to matching issues only |
Response
Section titled “Response”The response contains an estimate object, a historicalExamples array, and the echoed description.
estimate fields
Section titled “estimate fields”| Field | Type | Description |
|---|---|---|
p10 | number | null | Blended P10 cost in USD; null when neither local nor global data is available |
p50 | number | null | Blended P50 cost in USD |
p90 | number | null | Blended P90 cost in USD |
successRate | number | null | Fraction of completed issues (done ÷ total) for this repo with a non-null complexity; optionally filtered to the requested complexity. null when no qualifying issues exist |
sampleSize | number | Number of completed local issues informing the percentile estimates |
globalWeight | number | Fraction of the blended estimate drawn from the cross-tenant global baseline (see blending below) |
historicalExamples fields
Section titled “historicalExamples fields”Up to 20 recent completed issues from the same repo are returned as context.
| Field | Type | Description |
|---|---|---|
title | string | Issue title |
complexity | string | null | Assigned complexity tier, or null if unclassified |
totalCostUsd | number | Total LLM spend attributed to the issue |
totalDurationMs | number | Total agent execution time in milliseconds |
outcome | string | Always "success" (only completed issues are included) |
Blending
Section titled “Blending”When a repo has few completed issues, the local percentile figures are unreliable. The estimate blends local repo history with a cross-tenant global baseline using a linear weight:
localWeight = min(sampleSize / 30, 1.0)globalWeight = 1 − localWeightblendedPercentile = localWeight × localValue + globalWeight × globalValueA repo with 30 or more completed issues of the matching tier uses its local history exclusively (globalWeight = 0). A new repo with no completed issues uses the global baseline entirely (globalWeight = 1). Repos between those extremes interpolate. When only one side has data (local or global), that side is used directly regardless of weight.
globalWeight in the response communicates how much of the returned estimate comes from the cross-tenant baseline. A high globalWeight signals that the estimate is less repo-specific and should be interpreted with more uncertainty.
Surfaces
Section titled “Surfaces”The per-issue estimate is exposed in four places:
- Issue Intake Studio — the Estimate step shows P10/P50/P90 bands and historical examples before an issue is submitted to the pipeline.
- File Issue dialog — the Estimate panel provides an inline cost preview when drafting an issue from the dashboard.
colony_estimateMCP tool — available in Claude Code, Cursor, Claude Desktop, and other MCP-compatible editors connected to Colony Cloud. Inputs:repo(required,owner/nameformat),description(required),complexity(optional). See MCP & Editor Integration for setup.colony estimateCLI — the Self-Host analogue for monthly cost projection. It accepts--throughputand--mixflags and reads model routing from your config, producing a spend estimate without a live API call. Note this is a config-based projection (analogous toGET /pipeline/cost-projection), not a description-based per-issue estimator.