Skip to main content

Cost overview API

Reference

Lookup material for the Cost overview endpoints in Nirmata AIControls. They return the totals, rankings and series for a 24-hour, 7-day or 30-day window in bounded, cached reads, and they return partial results instead of failing the whole response.

Endpoints​

All four endpoints use GET and return JSON.

EndpointReturns
/api/v1/dashboards/cost/overviewThe top cards, month-to-date spend, team insights, rankings, and context optimization savings for one window.
/api/v1/dashboards/cost/spend-seriesSpend per bucket for one window: hourly for 24 hours, daily for 7 and 30 days.
/api/v1/dashboards/cost/request-rateAverage gateway calls, denials, and response blocks per minute for each bucket of one window.
/api/v1/dashboards/cost/activity-heatmapSessions and spend per day over a range that is independent of the window.

The older /api/v1/dashboards/cost endpoint is unchanged.

Authorization​

The responses include organization-wide email addresses and spend, so the endpoints accept only admin and viewer tokens. A builder token receives 403, and a request with missing or invalid credentials receives 401. Authorization always runs before any cached response is returned.

Send the token in the Authorization: Bearer header or the session cookie. A request that has a token query parameter is rejected with 400 before AIControls looks at the token, so credentials don't end up in URLs and access logs.

Parameters​

ParameterEndpointsDescription
from, tooverview, spend-series, request-rateThe window, as RFC 3339 timestamps. Required. See Window rules.
maxPointsrequest-rateNumber of buckets: 48, 96 (default), or 240. Other values round up to the next allowed value, and values above 240 give 240.
refreshallSet to 1 to bypass the cached response. See Caching.

The heatmap takes no window. Other query parameters are ignored.

Window rules​

to must be within 5 minutes of the current time, and to minus from must be 24 hours, 7 days, or 30 days, plus or minus one minute. Otherwise the endpoint returns 400 with {"error":"invalid_window"}.

The server canonicalizes the window: it rounds to down to the minute and sets from to to minus the window length. The response carries the canonical from and to. The window is selected by length, so a request for 7d ending a minute later is the same cached entry.

Common response fields​

FieldDescription
asOfWhen the response was computed.
from, toThe canonical window. On the heatmap, the effective range.
window24h, 7d, or 30d. Absent on the heatmap.
timezoneThe zone that day boundaries use: an IANA name, or a fixed offset such as +02:00. See Time zone.
cachedtrue when the response came from a cache entry, including one shared between replicas.
stale, staleAgeSecondsPresent only when true. The response is an older entry served while another replica recomputes it.

A cached response keeps its own from, to, and asOf, so you can see up to one cache lifetime of age.

Section status​

Every section of the overview, and every card in band, has its own status: ok, partial, or unavailable. When the status isn't ok, the section has a reason and any fields that could still be computed. The endpoint answers 200 even when every section fails.

ReasonMeaning
timeoutThe section did not finish within its 2-second deadline.
lane_busyThe dashboard read capacity was full. Retry shortly.
computing_elsewhereAnother replica is computing the response and no recent response was available to serve.
coverage_incompletePer-minute call counts don't cover the whole window. The card or series carries covered, the intervals that were summed.
not_readyA rollup that the section needs is still being built or was purged. The 7-day and 30-day sections never fall back to a slow read.
unavailableThe data store isn't configured.
errorAn internal error, which is logged and not included in the response.

Call counts begin when per-minute counting started, so a 7-day or 30-day window can report coverage_incomplete with covered set to the available interval until the counts reach the start of the window.

Overview response​

FieldDescription
metaplatformConnected, platformURL, proxyEnabled, and hasActivity. hasActivity is null when its check failed, never false.
band.requestsGateway calls in the window. Counts calls that were evaluated: LLM, MCP, and egress requests, excluding the internal AIControls identity.
band.deniedCalls denied by policy in the window.
band.responseBlockedResponses blocked by response-side controls.
band.activeUsers, band.activeAgentsDistinct users and agents that were active in the window.
band.spendUSDSpend in the window. Equal to the sum of the points that spend-series returns for the same window.
band.activePolicies, band.pendingApprovalsEnabled policies and unexpired pending approvals.
band.observerAI tool events and observed users in the window.
monthToDateusd, the spend since the start of the month in the reporting zone.
insightscaching, adoption (users new in this window compared with the previous one), wasteUSD, and budget. budget appears only when a monthly budget is set and month-to-date spend is available.
topDevelopers, topProjects, intentsUp to five rows each.
savingsToken savings from context optimization in the window.

Sections that rely on an approximate source list it in approximateSources. Historical session cost is attributed to the day a session started, and observer cost is placed by date, so bucket placement can differ from the exact timing while the window total stays exact.

Series responses​

EndpointFields
spend-seriespoints (t, spendUSD), totalUSD, bucketSeconds, status, reason. totalUSD is the sum of points.
request-ratepoints (t, requestsPerMinute, deniedPerMinute, blockedPerMinute), bucketSeconds, status, reason, covered. Each value is the average per minute over the covered part of the bucket. A bucket with no covered part is omitted.
activity-heatmaprange (from, to, days), days (date, sessions, spendUSD), sessionsSource (historical or audit), status, reason. The range is the days since the earliest data, at least 30 and at most 365.

Caching​

Responses are cached for 45 seconds, or 5 minutes for the heatmap. A response in which any section is not ok is cached for only 5 seconds, so partial results recover quickly. Errors are never cached.

With SQLite, each process keeps its own cache. With PostgreSQL, replicas share a cache table: one replica computes a response while the others serve the previous response with stale set, for up to twice the cache lifetime, or wait for the result.

Add refresh=1 to recompute a response. AIControls honors a refresh at most once every 10 seconds per response, across all replicas. A refresh inside that interval returns the cached response.

Resetting data and correcting agent identities clear the cache.

Time zone​

Day boundaries follow the zone that the database session uses, shown in timezone: with PostgreSQL, the session zone (storage.database.reportingTimezone, or the zone in the connection string, or the process zone); with SQLite, the process zone. Set reportingTimezone on every replica of a PostgreSQL deployment so that all replicas agree.

Daily values keep the day boundaries of the zone that was in effect when each day was recorded. After a zone change, daily points and the days at the edge of a window can differ from the new zone by up to the offset difference, and a window total that spans the change can be off by the activity in that interval. No action is needed.

Example​

curl -s -H "Authorization: Bearer $TOKEN" \
"https://aicontrols.example.com/api/v1/dashboards/cost/overview?from=2026-10-10T09:14:00Z&to=2026-10-11T09:14:00Z"
{
"asOf": "2026-10-11T09:14:03Z",
"from": "2026-10-10T09:14:00Z",
"to": "2026-10-11T09:14:00Z",
"window": "24h",
"timezone": "America/Los_Angeles",
"cached": false,
"meta": { "platformConnected": true, "proxyEnabled": true, "hasActivity": true },
"band": {
"requests": { "status": "ok", "value": 18342 },
"denied": { "status": "ok", "value": 27 },
"activeAgents": { "status": "partial", "reason": "not_ready" },
"spendUSD": { "status": "ok", "value": 412.5 }
},
"monthToDate": { "status": "ok", "usd": 5130.25 }
}