query_costs
Query time-bucketed spend for this account, optionally broken down by a dimension (service, region, linked_account, usage_type, operation, or identity) or by a custom cost-allocation tag (see list_cost_tags), and filtered by dimension values. identity is per-actor spend (e.g. an OpenAI or Anthropic api_key_id) where a provider's cost/usage API can group by it; not every provider populates it. Mirrors the GET /api/analytics endpoint used by the Plutus dashboard charts. All amounts are in USD, converted from each provider's own billing currency at the rate in effect on the day of the charge; the response states this in its currency field.
A row carries cost_basis only when its cost figure is an estimate rather than a real invoiced charge — e.g. Anthropic's identity-grain rows, priced from Anthropic's own published per-token rates because Anthropic's cost API has no per-key breakdown at all. Absent (null) cost_basis means the figure is invoiced. Always qualify an estimated figure as such when relaying it — do not present it with the same confidence as an invoiced one.
Where a provider reports usage alongside cost, a row also carries quantity and its unit (e.g. tokens, GB-month), plus a derived cost_per_unit in that same USD base. Always read cost_per_unit together with cost_per_unit_label, which names the denominator it is quoted against: token costs are quoted per 1,000 tokens ("per 1k tokens", cost_per_unit_scale: 1000), NOT per single token. All four fields are null when the provider reports no usage, and also when the rows behind a group carry more than one unit — a total mixing tokens and GB-month is not a quantity, so none is given.
The response also carries coverage.complete_through: cost data for the newest periods often has not landed yet (it arrives hours-to-a-day after the period it covers), so rows may end before end_date without that being a gap in spend — the newest period(s) simply aren't complete yet. coverage.lagging_sources, when non-empty, names a cost source that is behind or has stopped reporting; recent periods will under-count its spend. Unlike query_unit_costs, rows is NOT truncated to the horizon here — treat complete_through as a caveat on the newest bucket(s), not evidence anything is missing from the rows themselves.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| tag_key | No | Required when breakdown_by is "tag" — one of the tag_keys returned by list_cost_tags | |
| end_date | No | ISO-8601 end of the date range (exclusive) | |
| group_by | No | Time bucket size (default: day) | |
| start_date | No | ISO-8601 start of the date range (inclusive) | |
| cost_metric | No | Which cost figure to sum (default: "billed"). "amortized" spreads prepaid commitments (AWS Reserved Instances/Savings Plans, Azure reservations) across the term they cover instead of showing the full charge on the day it was billed. Only AWS, FOCUS and Azure sources ever differ from billed — every other provider writes amortized equal to billed, and that is the true figure for a SaaS subscription or LLM API, not a fallback. Amortized data only exists from 2026-08-04 onward and cannot be backfilled; rows before that date are billed-as-amortized regardless of which value is passed here. Not supported by get_cost_entries. | |
| breakdown_by | No | Dimension to break spend down by, or "tag" to break down by a virtual cost-allocation tag_key (see list_cost_tags) — requires tag_key. | |
| filter_region | No | Restrict to these region values | |
| filter_cluster | No | Restrict to these cluster values | |
| filter_service | No | Restrict to these service values | |
| cost_source_ids | No | Restrict to these provider ids (defaults to all enabled providers) | |
| filter_identity | No | Restrict to these identity values | |
| filter_workload | No | Restrict to these workload values | |
| filter_namespace | No | Restrict to these namespace values | |
| filter_operation | No | Restrict to these operation values | |
| filter_usage_type | No | Restrict to these usage_type values | |
| filter_resource_id | No | Restrict to these resource_id values | |
| filter_linked_account | No | Restrict to these linked_account values | |
| secondary_breakdown_by | No | A second dimension to break spend down by simultaneously with breakdown_by. Only pairs that some provider actually stores together on the same row are supported — e.g. (service, region), (service, linked_account), (usage_type, operation), and Kubernetes' (namespace, workload) — any other pair returns an error. Not applicable when breakdown_by is "tag". |