FOCUS cost export
GET /api/cost/export/focus returns your account’s aggregated cost history as a CSV using
column names from the FOCUS specification (FinOps Open Cost and
Usage Specification) — BilledCost, EffectiveCost, BillingCurrency, ServiceName, and so
on — so the file drops into a BI import or a spreadsheet pivot that was already built against
FOCUS column names.
This is the opposite direction from the FOCUS cost source, which imports a provider’s FOCUS export into Plutus. This page is about getting Plutus’s own aggregated data back out.
FOCUS-formatted, not FOCUS-conformant
Section titled “FOCUS-formatted, not FOCUS-conformant”The export borrows FOCUS’s column names and semantics for the data Plutus actually holds. It is not a spec-conformant FOCUS export, and it doesn’t claim to be.
A conformant export needs columns Plutus has no data model for: ListCost and ContractedCost
(rate-card views distinct from what was actually billed), ServiceCategory and ChargeCategory
(FOCUS’s own taxonomy, which no sync captures at ingest). Those columns are absent from the
file, not emitted full of nulls — a null-padded column looks conformant to the tool reading it
and silently misleads it, which is worse than a shorter, honest column set.
Check that whatever consumes the file tolerates the missing columns before wiring it into a pipeline that expects full FOCUS conformance.
Columns
Section titled “Columns”| Column | What it holds |
|---|---|
ChargePeriodStart, ChargePeriodEnd |
One UTC day. ChargePeriodEnd is exclusive and always one day after the start. |
BilledCost |
What the provider charged for that day. |
EffectiveCost |
The amortized figure — see the caveat below. |
BillingCurrency |
The currency the two cost columns are denominated in. |
ServiceName |
The service the spend is attributed to. |
ProviderName |
The cost source’s display name (for example, AWS), not its internal id. |
PricingQuantity, PricingUnit |
Quantity and unit, where the source reports them. |
Tags |
Provider tags as a JSON object. A row with no tags emits {}, not a blank cell. |
Rows are ordered oldest first.
What’s included
Section titled “What’s included”- Only cost sources currently enabled on the account. A source you’ve removed isn’t in the file.
- The
servicegrain only. Plutus stores the same spend once per breakdown dimension (service, region, account, usage type), so mixing dimensions into one file would double-count every dollar.serviceis the one dimension every provider populates, which is what lets the file honestly claim to cover the whole account. There’s no way to request a different dimension. - Virtual tags are not in the export. The
Tagscolumn carries the provider’s own tags. Tag rules you defined in Plutus (see Virtual tagging & cost allocation) are applied at query time and have no representation in this file.
Parameters
Section titled “Parameters”| Parameter | Required | Notes |
|---|---|---|
start_date |
yes | Inclusive. |
end_date |
yes | Exclusive. |
cost_source_ids |
no | Comma-separated. Narrows the export to specific sources; defaults to all enabled sources. |
currency |
no | native (default) or base. See below. |
GET /api/cost/export/focus?start_date=2026-07-01&end_date=2026-08-01There’s no download button in the app for this yet — it’s an API endpoint. It authenticates with your normal Plutus login session rather than an MCP or usage-ingestion API key, so opening the URL in a browser tab where you’re already signed in to Plutus downloads the file.
Native vs. base currency
Section titled “Native vs. base currency”By default each row carries the amount as the provider billed it, with BillingCurrency set
to that provider’s own currency. This is deliberate: FOCUS makes BillingCurrency a per-row
field precisely because a multi-provider bill is mixed-currency, and the point of a
FOCUS-formatted file is usually to reconcile line items against a provider’s own invoice, which
is denominated natively.
?currency=base is the opposite mode: every row is converted to the fixed USD base Plutus
aggregates on, and BillingCurrency reads USD on every row. Use it when you want one column
you can sum without an FX step; don’t use it when you’re reconciling against an invoice. See
Multi-currency.
Limits
Section titled “Limits”- 366 days per request. A wider window is rejected with an error rather than truncated. The export is synchronous — one HTTP request, no background job to poll — so the window has to stay small enough for a single response. Export a longer history as consecutive requests.
- Paid plans only. On Hobby, the endpoint returns a 403 pointing at the upgrade. See Plans & tiers.
The EffectiveCost caveat
Section titled “The EffectiveCost caveat”EffectiveCost is the amortized figure — prepaid commitments spread across the term they cover.
Amortized data only exists from the date Plutus started capturing it, and it can’t be
backfilled. Rows from before that date carry billed-as-amortized (EffectiveCost equal to
BilledCost), which is not a true amortized figure.
If your requested window starts before that date, the response carries an
X-Focus-Export-Warning header saying so. The export still runs — the warning doesn’t block it,
and it isn’t in the CSV body, so a script that only reads the body won’t see it. See
Billed vs. amortized cost.