Skip to content

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.

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.

FieldHorizonSQL condition
last24hUsdLast 24 hoursrecorded_at >= NOW() - INTERVAL '24 hours'
last7dUsdLast 7 daysrecorded_at >= NOW() - INTERVAL '7 days'
last30dUsdLast 30 daysrecorded_at >= NOW() - INTERVAL '30 days'
lifetimeUsdAll timeUnfiltered 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.

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.

ParameterRequiredValuesDefault
granularityYeshour, day, week, month
fromNoISO 8601 timestamp30 days before now
toNoISO 8601 timestampNow
repoNoowner/nameAll 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.

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:

GranularityMilliseconds per bucket
hour3,600,000
day86,400,000
week604,800,000
month2,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.

{
"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.

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.

ParameterRequiredValues
windowYes7d, 30d
FieldTypeDescription
modelstringModel identifier, or (unknown) when the model field is absent
totalCostUsdnumberTotal LLM spend attributed to this model in the window
issueCountnumberDistinct issues involving this model
invocationCountnumberTotal agent invocations for this model
maxTurnsRatenumber | nullFraction of invocations that hit the agent turn limit (max_turns_count / invocationCount); null when invocationCount is 0
noProgressRatenumber | nullFraction 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.

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.

FieldTypeDescription
monthlyLimitUsdnumber | nullSum 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.
spentUsdnumberCurrent UTC-month spend — sum of cost_usd from v1_cost_events since date_trunc('month', NOW() AT TIME ZONE 'UTC')
todaySpentUsdnumberCurrent UTC-day spend — sum of cost_usd since date_trunc('day', NOW() AT TIME ZONE 'UTC')
dailyLimitUsdnumber | nullmonthlyLimitUsd ÷ days in current UTC month; null when no cap is set
remainingUsdnumber | nullmax(0, monthlyLimitUsd − spentUsd); null when no cap is set
burnRateUsdPerDaynumber7-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)
projectedExhaustionDatestring | nullISO 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
isExhaustedbooleantrue when spentUsd >= monthlyLimitUsd

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.

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.

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.

ParameterRequiredFormatDefault
throughputPerDayYesPositive number
mixNosmall/medium/large as slash-separated integers summing to 10060/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.

For each complexity tier, the projected monthly cost is:

projectedMonthlyUsd = avgCostUsd × (mixPercent / 100) × throughputPerDay × 30

avgCostUsd 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.

FieldTypeDescription
complexitystringsmall, medium, or large
avgCostUsdnumberHistorical average cost per completed issue of this tier
p25CostUsdnumber | nullP25 per-issue cost; null when the tier has insufficient sample data
p75CostUsdnumber | nullP75 per-issue cost; null when the tier has insufficient sample data
sampleSizenumberCompleted issues informing this tier’s statistics
projectedMonthlyUsdnumberavgCostUsd × mixFraction × throughputPerDay × 30
FieldTypeDescription
throughputPerDaynumberThe throughputPerDay input echoed back
mixobjectThe resolved mix ({ small, medium, large }) echoed back
tiersarrayPer-tier entries in the order small, medium, large
totalProjectedMonthlyUsdnumberSum of projectedMonthlyUsd across all tiers
lowBandMonthlyUsdnumberSum of per-tier low-band figures (P25-based; tiers with null P25 contribute 0)
highBandMonthlyUsdnumberSum of per-tier high-band figures (P75-based; tiers with null P75 fall back to avgCostUsd)
sampleSizenumberTotal completed issues across all three tiers

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:

Terminal window
colony estimate --throughput 8 --mix 50/35/15

It accepts the same throughput and mix inputs and reads model routing from colony.config.yaml to estimate monthly spend without an API call.

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.

FieldRequiredTypeDescription
descriptionYesstringIssue description used to scope the estimate
complexityNosmall | medium | largeComplexity hint; when provided, percentiles and success rate are filtered to matching issues only

The response contains an estimate object, a historicalExamples array, and the echoed description.

FieldTypeDescription
p10number | nullBlended P10 cost in USD; null when neither local nor global data is available
p50number | nullBlended P50 cost in USD
p90number | nullBlended P90 cost in USD
successRatenumber | nullFraction 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
sampleSizenumberNumber of completed local issues informing the percentile estimates
globalWeightnumberFraction of the blended estimate drawn from the cross-tenant global baseline (see blending below)

Up to 20 recent completed issues from the same repo are returned as context.

FieldTypeDescription
titlestringIssue title
complexitystring | nullAssigned complexity tier, or null if unclassified
totalCostUsdnumberTotal LLM spend attributed to the issue
totalDurationMsnumberTotal agent execution time in milliseconds
outcomestringAlways "success" (only completed issues are included)

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 − localWeight
blendedPercentile = localWeight × localValue + globalWeight × globalValue

A 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.

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_estimate MCP tool — available in Claude Code, Cursor, Claude Desktop, and other MCP-compatible editors connected to Colony Cloud. Inputs: repo (required, owner/name format), description (required), complexity (optional). See MCP & Editor Integration for setup.
  • colony estimate CLI — the Self-Host analogue for monthly cost projection. It accepts --throughput and --mix flags and reads model routing from your config, producing a spend estimate without a live API call. Note this is a config-based projection (analogous to GET /pipeline/cost-projection), not a description-based per-issue estimator.