Skip to main content Skip to content

Showback (Cost Attribution)

Slice your total cloud bill by team, tag, or both. Endpoints for team and tag cost reports, how shared resources split, and how totals reconcile.

6 min read Last updated: 

Showback is the practice of slicing your total cloud bill by the organizational unit that incurred it — by team, by tag, or by both. ZopNight builds showback from the same daily cost records that power Reports.

By Team

Team attribution is derived from resource-team assignments, including resources a team owns through a resource group. Cost that belongs to no team is not a row in items. It is reported in unattributedCostUsd and unattributedCount.

GET /reports/teams

List cost per team for the selected period.

Response
{
"data": {
"items": [
{
"teamId": "team_001",
"teamName": "Platform",
"allocatedCostUsd": 4200.5,
"allocatedSavingsUsd": 310.25,
"resourceCount": 42,
"percentOfTotal": 33.7
}
],
"totalOrgCostUsd": 12450.5,
"totalOrgSavingsUsd": 480.0,
"unattributedCostUsd": 312.0,
"unattributedCount": 14,
"byProvider": { "aws": 9800.5, "gcp": 2650.0 },
"byResourceType": { "vm": 6100.0, "rds": 2200.0 },
"period": "2026-09",
"hasBilling": true,
"costSourceLabel": "Unblended Cost"
}
}

Query params: period (YYYY-MM, defaults to the current month), or from and to (YYYY-MM-DD, at most 366 days apart). Sort with sortBy (cost, savings, resourceCount, name) and sortOrder (asc or desc, default desc). The response may also carry a costDataMeta block that says how fresh the data is. costSourceLabel is explained on Billing.

GET /reports/teams/{teamID}

Per-team breakdown by provider and resource type.

GET /reports/teams/{teamID}/resources

Per-resource cost for a team — used for the drilldown table.

GET /reports/teams/trends

Daily / weekly / monthly trend series for all teams.

By Tag

Tag attribution covers cloud-native tags (AWS tags, GCP labels, Azure tags) plus accepted smart tags. Each row’s tagSource says where the tag came from: cloud, auto, inherited, derived, or mixed. Untagged cost is reported separately in untaggedCostUsd and untaggedCount.

Every tag endpoint below takes an optional tagScope:

  • accepted (default): cloud tags, tags inherited from a parent resource, and accepted smart tags.
  • all: also tags your tagging policies derive that nobody has accepted yet. They show as tagSource: "derived". A real cloud tag always wins over a derived value, and a resource covered only by a derived value is no longer counted as untagged.

Any other value returns 400. In the app, ticking Policy (not accepted) in the Tags tab’s Source filter sets tagScope=all for the chart and table, and the Coverage card then shows policy tags as their own band.

GET /reports/tags

List tag keys with attributed cost. Used to build the tag-key picker.

Response
{
"data": {
"items": [
{
"tagKey": "Environment",
"tagSource": "cloud",
"costUsd": 9800.5,
"savingsUsd": 360.0,
"resourceCount": 128,
"valueCount": 4
}
],
"totalCostUsd": 12450.5,
"totalSavingsUsd": 480.0,
"taggedCostUsd": 12138.5,
"untaggedCostUsd": 312.0,
"untaggedCount": 14,
"period": "2026-09",
"hasBilling": true,
"costSourceLabel": "Unblended Cost"
}
}

Keys-mode takes the same period, from, to, sortBy and sortOrder params as the team list. Without page and limit it returns every key. With them it returns one page plus total, page and limit. Add includeValues=true to inline each key’s values, byProvider and byResourceType for that page, so you don’t need one GET /reports/tags/{tagKey} call per key.

GET /reports/tags?unit=pairs&page={n}&limit={n}

Server-paginated list of (tagKey, tagValue) pairs. Powers the Tag Cost Attribution table without the prior 100-key client-side cap.

Response
{
"data": {
"items": [
{
"tagKey": "Environment",
"tagValue": "prod",
"tagSource": "cloud",
"costUsd": 4200.50,
"savingsUsd": 120.00,
"resourceCount": 32,
"prevCostUsd": 3950.00
}
],
"total": 248,
"page": 1,
"limit": 50,
"totalCostUsd": 12450.50,
"totalSavingsUsd": 480.00,
"untaggedCostUsd": 312.00,
"untaggedCount": 14,
"period": "2026-06",
"hasBilling": true,
"costSourceLabel": "Unblended Cost"
}
}
Query paramValues
sortBycost (default), savings, resourceCount, name
tagKey, tagValue, provider, resourceTypeComma-separated; all filters must match
pairKey + pairValueRepeat in matching pairs to filter on exact key/value tuples
sourcecloud, auto, inherited, mixed, derived (comma-separated); derived needs tagScope=all, otherwise 400
searchSubstring of key:value, up to 256 characters
GET /reports/tags/{tagKey}

List tag values for a key with their attributed cost.

GET /reports/tags/{tagKey}/values/{tagValue}/resources

List resources carrying a given tag value with their per-resource cost.

GET /reports/tags/trends

Daily / weekly / monthly trend series filtered by tag key, value, provider, or type.

Coverage & Reconciliation

  • Tagged vs. untagged. untaggedCostUsd and untaggedCount show how much cost carries no tag. Low coverage usually means tags are inconsistent across accounts — Smart Tags can close the gap.
  • Tag Coverage bar. The keys-mode response embeds taggedCostUsd — the per-resource-deduplicated tagged total, read from the same snapshot as untaggedCostUsd — so the Tag Coverage bar is computed within one data universe and reads exactly 0% when nothing is tagged. The field is omitted unless both totals queries (tagged and untagged) succeed — presenting one beside a zeroed other would render a false 0% or 100%; the UI then falls back to deriving coverage from the teams org total, which can drift by up to one snapshot cycle.
  • Reconcile to org total. In the team list, the sum of every team’s allocatedCostUsd plus unattributedCostUsd equals totalOrgCostUsd. The teams alone match it only when nothing is unattributed. percentOfTotal is measured against totalOrgCostUsd, so team percentages leave out the unattributed share.
  • Billed spend with no resource. With billing connected, charges that match no discovered resource (tax, support, data transfer, undiscovered services) can’t be assigned to a team. They land in unattributedCostUsd. See Billing.
  • Teams vs. tags. The team list reads cost records live. Tag reports read the daily snapshot. The two totals can differ until the snapshot catches up.
  • Days not built yet. If some days in the window haven’t been broken down by tag or team yet, tag endpoints and the team resources and trends endpoints return 409. They fill in automatically overnight.
  • Time alignment. period=YYYY-MM uses calendar month boundaries — not deploy-day or your fiscal calendar. For fiscal-month views, pass from and to, or export and re-aggregate downstream.

For exports of these reports as CSV/JSON, use the POST /reports/export endpoint documented in Reports & Analytics.

Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·