Documentation

Reports & Analytics

Track cloud costs, savings from automated scheduling, and monitor resource utilization across all your connected accounts.

Dashboard Summary

GET
/reports/summary

Get an overall cost and savings summary for the current period.

Responsejson
{
  "data": {
    "totalCostUSD": 12450.50,
    "totalSavingsUSD": 3280.75,
    "resourceCount": 156,
    "period": "2025-01"
  }
}

Cost Flow (Sankey)

A configurable Sankey view of how cost flows across providers, accounts, regions, resource types, services, purchase types, and teams. The default flow is Provider → Account → ResourceType → Team and can be reshaped to any ordered sequence of dimensions; the URL is shareable so a drilldown can be sent in chat.

Supported dimensions

  • provider
  • cloud_account_id
  • region
  • resource_type
  • service_name
  • purchase_type
  • team_id
  • resource_uid (drilldown only)

Overlays

  • Savings overlay — highlights links carrying idle, orphan, or right-sizing savings opportunities surfaced by Recommendations.
  • Unattributed overlay — surfaces cost flowing to resources missing team or tag attribution. Use this to find gaps in Auto-Tagging coverage.
GET
/reports/costs/breakdown

Generic GROUP BY on cost_records. Reusable for the Sankey, treemaps, custom dashboards, anything future.

Query parameters:

  • dims — comma-separated dimension list, in order. Allowlisted to the dimensions above.
  • from / to — ISO 8601 date range.
  • filter[dim]=value — repeatable, scopes the breakdown.
Examplebash
curl "https://zopnight.com/api/reports/costs/breakdown?dims=provider,cloud_account_id,resource_type,team_id&from=2026-04-01&to=2026-04-27" \
  -H "Authorization: Bearer <token>"
Responsejson
{
  "data": {
    "nodes": [
      { "id": "aws", "dim": "provider" },
      { "id": "aws|123456789012", "dim": "cloud_account_id", "label": "Production AWS" },
      { "id": "aws|123456789012|aws-ec2", "dim": "resource_type" },
      { "id": "aws|123456789012|aws-ec2|team_platform", "dim": "team_id", "label": "Platform" }
    ],
    "links": [
      { "source": "aws", "target": "aws|123456789012", "valueUSD": 4200.50 },
      { "source": "aws|123456789012", "target": "aws|123456789012|aws-ec2", "valueUSD": 2800.00 },
      { "source": "aws|123456789012|aws-ec2", "target": "aws|123456789012|aws-ec2|team_platform", "valueUSD": 1900.50 }
    ],
    "totalUSD": 4200.50
  }
}

Single source of truth

Every cost-reporting endpoint — /reports/summary, /reports/trends, /reports/costs/breakdown, /reports/teams, /reports/tags — reads from the same cost_records fact table. Team and tag attribution is resolved at read-time, so totals always reconcile to the provider total without a snapshot rebuild.

Export

The Sankey supports CSV and PNG export. CSV exports the underlying flow rows (source, target, dimension, value); PNG exports the rendered diagram with the same URL-encoded state.

Cost Anomaly Detection

ZopNight detects unusual cost spikes across five dimensions (org, cloud account, resource group, resource, team) using percentage deviation and z-score analysis, with 14-day root-cause attribution. See Cost Anomaly Detection for the full feature, including detection algorithm, notification cooldown, dedup, and the two-level drawer.

GET
/reports/anomalies

List anomaly records for a window. Suppressed records map to severity info.

Cost Trends

GET
/reports/trends

Get daily cost and savings trend data for charts and dashboards.

Responsejson
{
  "data": {
    "items": [
      {
        "date": "2025-01-15",
        "costUSD": 425.30,
        "savingsUSD": 112.50
      },
      {
        "date": "2025-01-16",
        "costUSD": 418.20,
        "savingsUSD": 119.80
      }
    ]
  }
}
GET
/reports/cost-history

Long-range cost history for charts that span multiple months. Accepts granularity (daily, weekly, monthly) and a date range.

GET
/reports/metrics

Aggregate utilization metrics across the org (CPU, memory, disk) used by the dashboard hero. Backed by the discoverer's metrics enrichment.

GET
/reports/resources/metrics

Per-resource utilization metrics over a window (CPU, memory, network). Used by the resource detail drawer.

GET
/reports/resources/activity

Per-resource activity timeline (state transitions, scheduler events, action submissions, configuration changes).

POST
/reports/export

Export a cost report as CSV or JSON. Accepts the same dimensions and filters as the report endpoints; returns a download URL.

Requestbash
curl -X POST https://zopnight.com/api/reports/export \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "report": "costs/breakdown",
    "format": "csv",
    "dimensions": ["provider", "team_id"],
    "from": "2026-04-01",
    "to": "2026-04-30"
  }'
Responsejson
{
  "data": {
    "downloadURL": "https://zopnight.com/exports/cost-2026-04.csv",
    "expiresAt": "2026-04-30T01:00:00Z"
  }
}

Resource Costs

GET
/reports/costs/resources

Get per-resource cost breakdown.

Examplebash
curl "https://zopnight.com/api/reports/costs/resources?page=1&limit=20" \
  -H "Authorization: Bearer <token>"

Provider Summary

GET
/reports/providers/summary

Get cost and resource count breakdown by cloud provider.

Responsejson
{
  "data": {
    "aws": {
      "count": 85,
      "costUSD": 7200.00
    },
    "gcp": {
      "count": 42,
      "costUSD": 3150.50
    },
    "azure": {
      "count": 29,
      "costUSD": 2100.00
    }
  }
}

Resource Summary

GET
/reports/resources/summary

Get resource count hierarchy grouped by provider and cloud account.

Responsejson
{
  "data": {
    "providers": [
      {
        "name": "aws",
        "total": 85,
        "accounts": [
          {
            "id": "ca_001",
            "name": "Production AWS",
            "total": 60,
            "byType": {
              "aws-ec2": 25,
              "aws-rds": 8,
              "aws-eks": 3
            }
          }
        ]
      }
    ],
    "total": 156
  }
}

Cost Attribution (Showback)

Slice cost by team (derived from resource group ownership) or by tag (cloud tags, GCP labels, Azure tags, and accepted auto-tag predictions). Both dimensions are computed from the same daily billing rollup, so team and tag totals always reconcile to the provider total.

By Team

GET
/reports/teams

List cost per team for the selected period.

Responsejson
{
  "data": [
    {
      "teamID": "team_001",
      "teamName": "Platform",
      "costUSD": 4200.50,
      "resourceCount": 42,
      "percentOfTotal": 33.7
    }
  ]
}
GET
/reports/teams/{teamID}

Get a per-team breakdown by provider and resource type.

GET
/reports/teams/{teamID}/resources

List resources attributed to a team with their individual cost.

GET
/reports/teams/trends

Daily/weekly/monthly trend series for all teams.

By Tag

GET
/reports/tags

List tag keys that have attributed cost (cloud tags, GCP labels, Azure tags, auto-tag predictions).

Responsejson
{
  "data": [
    {
      "tagKey": "Environment",
      "coverage": {
        "tagged": 128,
        "untagged": 18
      },
      "costUSD": 12450.50
    }
  ]
}
GET
/reports/tags/{tagKey}

List tag values for a given key and their attributed cost.

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

List resources that carry a given tag value with individual cost.

GET
/reports/tags/trends

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

Tag Coverage

coverage.tagged vs coverage.untagged reflects how many discovered resources carry the key in the current period. Low coverage usually means the tag key is inconsistent across accounts — Auto-Tagging can help close the gap.

Monthly Snapshots

GET
/reports/snapshots

Get historical monthly report snapshots.

Responsejson
{
  "data": [
    {
      "id": "snap_001",
      "period": "2025-01",
      "totalCostUSD": 12450.50,
      "totalSavingsUSD": 3280.75,
      "resourceCount": 156,
      "createdAt": "2025-02-01T00:00:00Z"
    },
    {
      "id": "snap_002",
      "period": "2024-12",
      "totalCostUSD": 13100.00,
      "totalSavingsUSD": 2900.00,
      "resourceCount": 148,
      "createdAt": "2025-01-01T00:00:00Z"
    }
  ]
}

Team Budgets

Set monthly cost budgets for teams and track spending against them.

GET
/budgets/summary

Get organization-wide budget summary.

Responsejson
{
  "data": {
    "totalBudgetUSD": 25000.00,
    "totalSpendUSD": 18500.00,
    "percentUsed": 74.0,
    "budgetCount": 5,
    "overBudgetCount": 1
  }
}
GET
/budgets

List all team budgets.

POST
/budgets

Create a team budget.

Requestbash
curl -X POST https://zopnight.com/api/budgets \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "teamName": "Platform Team",
    "resourceGroupID": "grp_abc123",
    "monthlyBudgetUSD": 5000.00,
    "alertThresholdPercent": 80
  }'
Responsejson
{
  "data": {
    "id": "bgt_abc123",
    "teamName": "Platform Team",
    "resourceGroupID": "grp_abc123",
    "monthlyBudgetUSD": 5000.00,
    "alertThresholdPercent": 80,
    "currentSpendUSD": 3200.00,
    "remainingUSD": 1800.00,
    "percentUsed": 64.0,
    "status": "green",
    "createdAt": "2025-01-01T00:00:00Z",
    "updatedAt": "2025-01-20T08:00:00Z"
  }
}
PUT
/budgets/{budgetID}

Update a team budget.

DELETE
/budgets/{budgetID}

Delete a team budget.

Budget Status Indicators

StatusConditionDescription
greenSpend < alert thresholdSpending is within normal range
yellowSpend >= alert thresholdSpending has crossed the configured alert threshold
redSpend >= 100% of budgetBudget has been exceeded

Scheduler Events

View a log of scheduler-triggered events showing which schedules fired and what actions were taken.

GET
/events

List scheduler events.

Responsejson
{
  "data": [
    {
      "id": "evt_001",
      "scheduleID": "sch_abc123",
      "action": "stop",
      "triggeredAt": "2025-01-20T18:00:00Z",
      "resources": ["i-0abc123def456", "i-0def789abc012"],
      "status": "completed"
    }
  ]
}
POST
/events

Record a scheduler event (primarily used internally by the scheduler service).

Unit Economics

Unit economics correlate spend with business KPIs — cost per order, cost per active user, cost per build minute — so teams can compare cost movement against demand rather than treating spend as a raw line item. Define a metric in /unit-metrics (push, pull, or CSV ingestion), then send values for it and read the resulting series back through Reports.

POST
/unit-metric-values/{id}

Push a batch of values for a unit metric. Returns the number of rows ingested. Use for low-volume push integrations and webhooks.

POST
/unit-metric-values/{id}/csv

Upload a CSV of historical values. Accepts a single CSV file per request; rows are upserted by timestamp.

POST
/unit-metric-values/{id}/test-pull

Run the configured pull integration once and return the rows it produced — without persisting anything. Used by the metric editor's 'Test connection' button.

DELETE
/unit-metric-values/{id}

Drop every stored value for a metric. Useful when reseeding from a corrected source.

GET
/reports/unit-economics

Time-series of cost-per-unit for a chosen metric, with optional filters (provider, team, tag). Used by the Unit Economics chart on the cost dashboard.

Metric definitions live in Config

The metric definitions themselves (name, ingestion mode, pull config) are managed at /unit-metrics and /unit-metrics/{id}. The endpoints above handle values and reads only. The aggregator runs a daily unit-metrics-pull cron at 04:15 UTC that fetches pull-mode metrics on schedule.