Skip to content

Cost ​

Workspace-scoped cost rollups plus a CRUD surface for the per-model price table. Cost is computed from inference-log rows by joining each (prompt_tokens, completion_tokens) against the active PriceRate for the model — see packages/observability/cost.py for the math. The dashboard at 10 — Cost dashboard is the primary consumer.

The router lives at packages/observability/cost_routes.py.

Endpoints ​

MethodPathAuthSummary
GET/admin/cost/by-modelBearerPer-(model, adapter) rollup for the workspace.
GET/admin/cost/by-dayBearerDaily rollup (sparkline source).
GET/admin/cost/pricesBearerList configured per-model rates.
PUT/admin/cost/pricesBearerUpsert one model's rate (platform admin only).
DELETE/admin/cost/prices/{model_id}BearerDrop a model's configured rate.

GET /admin/cost/by-model ​

Query params: since, until (ISO-8601, optional). Returns {"rows": [CostRollupRow]}:

json
{
  "rows": [
    {
      "workspace_id": "default",
      "model_id": "llama3.2:3b",
      "adapter_id": null,
      "prompt_tokens": 12480,
      "completion_tokens": 4900,
      "total_tokens": 17380,
      "request_count": 64,
      "amount": 0.0034,
      "currency": "USD"
    }
  ]
}
bash
curl -H "Authorization: Bearer $BIGWAVE_ADMIN_TOKEN" \
  "http://localhost:8000/admin/cost/by-model?since=2026-04-01T00:00:00Z"

GET /admin/cost/by-day ​

Same time bounds as by-model. Returns {"rows": [CostDailyRow]}, one row per UTC calendar day. Used to draw the cost sparkline on the overview page.

bash
curl -H "Authorization: Bearer $BIGWAVE_ADMIN_TOKEN" \
  "http://localhost:8000/admin/cost/by-day?since=2026-04-01T00:00:00Z&until=2026-05-01T00:00:00Z"

GET /admin/cost/prices ​

Lists the currently-configured per-1 000-token rates. The price table is in-memory on app.state.cost_repo.prices; persisted rates are reloaded at lifespan boot.

json
{
  "rates": [
    {
      "model_id": "llama3.2:3b",
      "prompt_per_1k": 0.0,
      "completion_per_1k": 0.0,
      "currency": "USD"
    },
    {
      "model_id": "gpt-4o-mini",
      "prompt_per_1k": 0.15,
      "completion_per_1k": 0.60,
      "currency": "USD"
    }
  ]
}

PUT /admin/cost/prices ​

Body schema is the in-route _PriceRateBody (packages/observability/cost_routes.py:22):

json
{
  "model_id": "gpt-4o-mini",
  "prompt_per_1k": 0.15,
  "completion_per_1k": 0.60,
  "currency": "USD"
}

Returns {"status": "ok", "model_id": "..."}. Negative rates are rejected with 400.

bash
curl -X PUT -H "Authorization: Bearer $BIGWAVE_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model_id":"gpt-4o-mini","prompt_per_1k":0.15,"completion_per_1k":0.60}' \
  http://localhost:8000/admin/cost/prices

DELETE /admin/cost/prices/{model_id} ​

Removes the configured rate for model_id. Subsequent rollups for that model report amount = 0.0 until a rate is re-uploaded.

Operator notes ​

  • Workspace fence. Rollup routes filter on the bearer principal's workspace; price routes are global (the rate table is shared across tenants — tenants do not see each other's consumption, but do share the catalog of rates). See workspace fence.
  • Platform admin vs workspace admin. Until RBAC ships, the bearer token gates everything; the operator-level BIGWAVE_ADMIN_TOKEN is the only role. In intent: workspace admins read rates, platform admins edit them.
  • 503 causes. app.state.cost_repo is wired in lifespan; routes return 503 with "cost rollup repository not initialised" when missing.
  • Cost source of truth. Rollups are computed from inference_log (see /admin/inference); rows blocked by guardrails (status=blocked) carry zero token counts and therefore contribute zero amount.
  • Concept page. See 10 — Cost dashboard for the operator-facing tour.

Dual-licensed: MIT OR Apache-2.0