Skip to main content Skip to content

Cost query API

Query reconciled cost data (by service, region, team, tag, or any combination) with grouping, filtering, and time-range pagination.

4 min read Last updated: 

Base URL and auth

Terminal window
https://api.zop.dev/v1

All requests require a personal access token in the Authorization: Bearer … header. The Cost query endpoints are read-only and accept any PAT that has been granted the cost:read scope (granted by default to every PAT).

Query reconciled cost

Terminal window
POST /cost/query

The cost query endpoint returns reconciled spend across any combination of dimensions, filters, and time ranges. Results are already reconciled to your actual billing export (Cost Explorer, BigQuery, Cost Management); no rack-rate conversion, no estimates.

Request body

Terminal window
{
"timeRange": {
"start": "2026-05-01",
"end": "2026-05-31",
"granularity": "day"
},
"groupBy": ["service", "team"],
"filters": {
"providers": ["aws", "gcp"],
"environments": ["prod", "stage"],
"tags": {
"include": [{ "key": "cost-center", "value": "platform" }],
"exclude": [{ "key": "ignore-cost", "value": "true" }]
}
},
"currency": "USD",
"page": 1,
"pageSize": 1000
}

Example

Terminal window
curl -X POST "https://api.zop.dev/v1/cost/query" \
-H "Authorization: Bearer $ZOPNIGHT_PAT" \
-H "Content-Type: application/json" \
-d '{
"timeRange": { "start": "2026-05-01", "end": "2026-05-31", "granularity": "day" },
"groupBy": ["service", "team"],
"filters": { "providers": ["aws", "gcp"] },
"currency": "USD"
}'

Supported groupBy dimensions

  • provider; aws, gcp, azure.
  • account; cloud account ID.
  • service; provider service (e.g. ec2, rds, cloud-storage, azure-functions).
  • resourceType; sub-service type.
  • region; provider region.
  • environment; prod, stage, uat, dev.
  • team; owning team slug.
  • tag:<key>; group by a tag key, e.g. tag:cost-center.
  • resource; resource-level breakdown (limited to 10k results per query).

You can group by up to 4 dimensions per query. Order matters for cardinality; put the lowest-cardinality dimension first.

Granularity

  • day; daily buckets. Max 92-day range per query.
  • month; monthly buckets. Max 24-month range per query.
  • hour; hourly buckets. Max 7-day range per query. Available only on the Enterprise tier.

Response

Terminal window
{
"data": [
{
"service": "ec2",
"team": "payments-platform",
"buckets": [
{ "date": "2026-05-01", "amount": 412.18, "currency": "USD" },
{ "date": "2026-05-02", "amount": 408.94, "currency": "USD" }
],
"total": { "amount": 12438.21, "currency": "USD" }
}
],
"pagination": { "page": 1, "pageSize": 1000, "total": 47 },
"reconciliation": {
"billingExport": "aws-cur-2026-05",
"lastReconciledAt": "2026-06-01T03:12:00Z"
}
}

Anomaly detection

Terminal window
GET /cost/anomalies

Returns anomalies detected against the 7-day rolling average across five dimensions: org, cloud account, resource group, resource, and team. See Cost anomalies for the detection method and severity bands.

Query parameters

NameTypeDescription
sincedateISO-8601 date. Default: 7 days ago.
minDeltanumberMinimum dollar delta to include. Default: $100/day.
dimensionenumFilter to one dimension.

Budgets

Terminal window
GET /cost/budgets
POST /cost/budgets
PATCH /cost/budgets/:id
DELETE /cost/budgets/:id

Budgets are computed live from the Cost Graph; there is no nightly snapshot delay. A budget update takes effect on the next query.

Budget object

Terminal window
{
"id": "bud_01HK3...",
"name": "Payments. May 2026",
"scope": { "team": "payments-platform" },
"period": "month",
"amount": 50000,
"currency": "USD",
"alerts": [
{ "threshold": 0.7, "channels": ["slack:#payments-finops"] },
{ "threshold": 0.9, "channels": ["slack:#payments-finops", "email:lead@example.com"] }
]
}

Export

For large pulls (resource-level, full month, every account), use the export flow:

Terminal window
POST /cost/export
GET /cost/export/:id

The first call enqueues an export job; the second polls its status. Completed exports are delivered as CSV, JSON, or Parquet to a signed URL; or directly to your S3 / GCS / Azure Blob bucket on the Enterprise tier.

Rate limits

  • Read endpoints (POST /cost/query, GET /cost/anomalies, GET /cost/budgets, GET /cost/export/:id): 600 requests/min per workspace.
  • Write and export endpoints (POST /cost/export, budget create/update/delete): 60 requests/min per workspace.

Headers X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset are returned on every response.

Errors

Errors use standard HTTP status codes. The body carries a machine-readable code, a human-readable message, and the numeric status.

StatusMeaning
400Invalid or malformed parameters (bad granularity, range over the granularity limit, unknown groupBy dimension).
401Missing or invalid token.
403Token lacks the required scope (e.g. cost:read, or write scope for budget mutations).
404Budget or export job not found, or not visible to the token’s role.
429Rate limited; see Rate limits.
5xxServer error; safe to retry with backoff.
Terminal window
{
"error": {
"code": "invalid_request",
"message": "granularity \"hour\" allows a maximum range of 7 days",
"status": 400
}
}
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001 · zero-trust· 30% average cloud cost cut· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001 · zero-trust· 30% average cloud cost cut· 4 platforms · 1 console·