SOLWYN
Commands

costs

Grouped cost breakdowns, paginated events, uncapped totals, raw and aggregated export, and the analytics subcommands — baseline, unit economics, drift, priced models, and simulation

costs is a command group. Run it bare for a grouped breakdown of a project's spend over a window, or use a subcommand for a specific view:

CommandPurpose
solwyn costsAggregate spend grouped by one dimension. Top 100 groups.
solwyn costs eventsPage through individual cost events. Production and above.
solwyn costs totalThe uncapped total for the window, for reconciling a truncated breakdown.
solwyn costs exportStream CSV or NDJSON to stdout.
solwyn costs baselineThe daily-spend baseline anomaly rules arm against.
solwyn costs unit-economicsCost per request, per run, and tokens per dollar, with a comparison window.
solwyn costs driftStored actual cost versus the SDK's pre-flight estimates.
solwyn costs priced-modelsEvery model the pricing catalog can bill.
solwyn costs simulateReplay the window's usage against one current priced model.

Every subcommand accepts either credential and requires a project, resolved from --project, SOLWYN_PROJECT_ID, or default_project in your config file. The one exception is costs --account, which rolls up every project and requires a user login instead.

All of these commands move quantities and selectors only: dollars, token counts, model and provider names, your own tag labels. No field in any response can carry a prompt or a completion. See Privacy.

Shared filters

costs, events, total, and export take the same filter set. Filters go after the subcommand — solwyn costs --model gpt-5 total is a usage error with a hint to reorder.

OptionTypePurpose
--rangestringPreset window. Default 7d (30d for export). Allowed presets depend on your plan and are validated by the API.
--from, --toISO 8601 with timezoneAn explicit window. Both required together; --to is exclusive and must be later. Replaces --range.
--modelstringFilter to one model.
--providerstringFilter to one provider.
--modalitystringtext, image, audio, video, or embedding.
--statusstringsuccess, error, or budget_denied.
--service-tierstringProvider service tier, for example flex or priority.
--provider-regionstringServing region.
--agent-runstringA run id (run_ plus 32 hex characters) or a run name.
--failover-reasonstringcircuit_open, primary_error, model_fallback, or cost_routed.
--model-fallback / --no-model-fallbackflag pairOnly calls that were (or were not) served by a fallback model.
--provider-fallback / --no-provider-fallbackflag pairOnly calls that were (or were not) served by a fallback provider.
--tagkey=value, repeatableFilter by an attribution tag. Team and above. Split on the first =, so values may contain =; duplicate keys are rejected.

Window and tag validation happens locally, before any request. A bad value exits 2 with invalid_cost_query and no network call.

When the API narrows your window to your plan's retention, a note goes to stderr in both output formats:

Retention clamped window: 2026-07-02T00:00:00Z to 2026-07-31T00:00:00Z (requested 2026-07-01T00:00:00Z to 2026-07-31T00:00:00Z).

The JSON payloads carry the same information as a window object with requested_from, requested_to, effective_from, effective_to, and retention_clamped.

costs

Aggregate spend for the window, grouped by one dimension.

Terminal
solwyn --project <project_id> costs [--group-by <dimension>] [--range <preset>] [filters...]
solwyn costs --account [--group-by project|<dimension>] [--range <preset>]
OptionTypeDefaultPurpose
--group-bystringmodel (project with --account)A dimension from your plan's billing capabilities, or tag:<key> on Team and above.
--accountbooleanfalseRoll up every project in the account. Requires JWT.
Contract
Authany; --account requires JWT
Exit codes0 success · 1 generic/API · 2 usage · 3 auth · 5 not found
JSON schemasolwyn.costs.v1; solwyn.account_costs.v1 with --account

Dimensions in use today include day, model, provider, status, service_tier, provider_region, failover_reason, agent_run, and tag:<key>. The CLI does not enumerate them — your plan does. When the API refuses a grouping or range, the CLI appends your plan's allowed values to the error's hint and exits 2.

Terminal
$ solwyn --project proj_0123456789abcdef01234567 costs --range 30d --group-by model
Group       Provider      Cost  Input  Output  Calls  Unpriced  Local
gpt-5-mini  openai    2.500000   2400     680      8         0      2
ColumnMeaning
GroupThe grouping key. — when the API returns none.
ProviderProvider for the group. - when the group spans providers, for example when grouping by day.
CostPriced total in USD.
Input / OutputTotal input and output tokens.
CallsNumber of calls in the group.
UnpricedCalls recorded with no observable billable quantity — never a fabricated $0.
LocalCalls to zero-cost local providers (ollama, vllm, lmstudio), recorded for visibility.
Run nameAppears only when grouping by agent_run and a run carries a name.

Two more notes can appear on stderr: showing top 100 groups when the breakdown is truncated, and Savings: $…; upper …; blocked calls N. when hard-deny blocked spend in the window. Use costs total for the untruncated figure.

The Unpriced and Local lanes exist because Solwyn records only quantities and selectors — a call whose billable quantity is unobservable is shown, not invented. See Surface coverage.

JSON output

{
  "schema": "solwyn.costs.v1",
  "project_id": "proj_0123456789abcdef01234567",
  "range": "7d",
  "group_by": "model",
  "groups": [
    {
      "group_key": "gpt-5-mini", "provider": "openai", "modality": null, "agent_run_name": null,
      "total_cost": 2.5, "total_input_tokens": 2400, "total_output_tokens": 680,
      "call_count": 8, "unpriced_call_count": 0, "local_call_count": 2
    }
  ],
  "truncated": false,
  "window": {
    "requested_from": "2026-07-09T00:00:00Z", "requested_to": "2026-07-16T00:00:00Z",
    "effective_from": "2026-07-09T00:00:00Z", "effective_to": "2026-07-16T00:00:00Z",
    "retention_clamped": false
  }
}

Pretty-printed here; the CLI emits one line. truncated and window are always present; savings appears only when non-null.

Account rollup

--account groups by project by default and draws an eight-level sparkline of daily spend. Only --model, --provider, --modality, --group-by, and window filters are accepted; the others exit 2.

Terminal
$ solwyn costs --account
Project  Window cost  Current period  Calls  Daily
Alpha       2.500000        3.000000      8  ▃█

On a plan without analytics, the table collapses to Project and Current period, and the JSON sets analytics_withheld: true rather than emitting zeros.

Budget and quota periods use server receive time (received_at). Analytics use the event's stored timestamp: a backdated batch counts against the applicable budget/quota period when received, while appearing on its original analytics day within Core's clock and retention bounds. Future skew can be clamped; a configured past horizon can clamp older timestamps. Backdating cannot bypass current-period limits.

costs events

Page through individual cost events. Production and above.

Terminal
solwyn --project <project_id> costs events [--limit 1-100] [--cursor <c>] [--all] [filters...]
OptionTypeDefaultPurpose
--limitinteger 1–10025Events per page.
--cursorstringnoneContinue from a previous page.
--allbooleanfalseFollow all remaining pages from the optional starting cursor; --limit remains per-page.
Contract
Authany
Exit codes0 success · 1 generic/API · 2 usage · 3 auth · 5 not found
JSON schemasolwyn.costs.events.v1

The table shows Time, Model, Provider, Cost, Denied cost, Deny source, Deny reason, SDK instance, and Tags. An unpriced event shows — for cost. When more pages exist, the table view prints the next cursor to stderr; in JSON it is the next_cursor field alongside has_more.

Each JSON item carries ids, provider and model, modality, region and service tier, ten token counters, cost and denied cost, price flags, a media breakdown for image, audio, and video calls, your tags, status, latency, the SDK instance id, and a timestamp. Event rows deliberately omit call_id, the provider-fallback flag, and the failover reason — use a raw export for those.

With --all, filters persist and rows remain in Core order; exhausted JSON has next_cursor=null, has_more=false. Repeated cursors, inconsistent continuation, malformed responses and later-page failures produce a nonzero exit with no partial success stdout.

Events require Production except the first-page onboarding probe (--limit 1 without a cursor). On a pre-Production plan, costs events --limit 1 --all can pass that probe and receive 402 on a cursor page. The command exits 1 and emits no partial stdout; first-page success is not permission to fetch all events.

costs total

The server-authoritative total for the window, not capped to the top 100 groups.

Terminal
$ solwyn --project proj_0123456789abcdef01234567 costs total --range 30d
Cost      Input  Output  Calls  Unpriced  Local
2.500000  2400   680     8      0         2
Contract
Authany
Exit codes0 success · 1 generic/API · 2 usage · 3 auth · 5 not found
JSON schemasolwyn.costs.total.v1

Takes the shared filters and nothing else. The JSON payload adds project_id, range, window, and savings when present.

costs export

Stream the window as CSV or newline-delimited JSON to stdout.

Terminal
solwyn --project <project_id> costs export [--format csv|json] [--group-by <dimension>] [--range <preset>] [filters...] > costs.csv
OptionTypeDefaultPurpose
--formatcsv | jsoncsvjson is NDJSON, one object per line.
--group-bystringunsetOmit for a raw per-event export (Team and above). Supply a dimension for an aggregated export (Production and above).
--rangestring30dNote the different default.
Contract
Authany
Exit codes0 success · 1 generic/API · 2 usage · 3 auth · 5 not found
JSON schemastream (CSV or NDJSON), not an envelope

The response bytes are copied to stdout unchanged. There is no output-file flag — redirect. --json does not wrap the stream. Requested/effective window and retention headers, plus X-Solwyn-Export-Snapshot, are echoed on stderr when supplied. Keep streams separate and retain that metadata with the export.

Raw exports are capped at 25,000 events or 32 MiB; aggregate exports at 10,000 pricing subgroups or 32 MiB. Oversized exports return 422/exit 2 with no partial result, rather than a silently truncated file. Narrow the window. A connection failure after streaming begins can still leave incomplete bytes and is never replayed automatically. Write to a temporary file and rename only on success, preserving CSV formula-safety prefixes.

costs baseline

The trailing daily-spend baseline that daily-anomaly alert rules arm against.

Terminal
$ solwyn --project proj_0123456789abcdef01234567 costs baseline --days 7
Lookback  Days with data  Mean / day  Stdev / day  Armed  Freshness
       7               6    1.250000     0.375000  yes    committed closed days
OptionTypeDefaultPurpose
--daysinteger 3–307Lookback window.
Contract
Authany
Exit codes0 success · 1 generic/API · 2 usage · 3 auth · 5 not found
JSON schemasolwyn.costs.baseline.v1

A baseline is armed once at least three days in the lookback had spend; until then, anomaly rules skip evaluation. Figures use transactional daily spend excluding today; closed days reflect committed metadata immediately.

costs unit-economics

Per-unit cost metrics for the window, compared against the preceding window of the same length.

Terminal
$ solwyn --project proj_0123456789abcdef01234567 costs unit-economics --range 30d --cause
Metric                    Value    Previous    Delta  Context
Cost / request         0.012500    0.010000  +25.00%  200 requests
Tokens / dollar    50000.000000           —        —  2.0M tokens served
Avg prompt tokens    120.000000  100.000000  +20.00%  200 requests
OptionTypeDefaultPurpose
--range7d | 30d | 90d30dThe window. This subcommand has no --from/--to.
--vs-prev / --no-vs-prevboolean--vs-prevCompare with the preceding same-length window.
--causebooleanfalseAsk the API for its inferred cost drivers.
Contract
Authany
Exit codes0 success · 1 generic/API · 2 usage · 3 auth · 5 not found
JSON schemasolwyn.costs.unit-economics.v1

A Cost / agent run row appears when the window contained runs. A delta is — rather than a fake zero whenever the previous value is missing or not positive. With --cause, a suspected cause and its confidence print to stderr, for example Suspected cause (high): Model mix shifted toward a higher-cost target.

costs drift

How far stored actual cost diverged from the pre-flight estimate the SDK made before each call, per provider and model.

Terminal
$ solwyn --project proj_0123456789abcdef01234567 costs drift --range 7d
Provider  Model     Actual  Estimated  Difference  Events
openai    gpt-5  12.500000  10.000000   +2.500000      80
Total     —      12.500000  10.000000   +2.500000      80
OptionTypeDefaultPurpose
--rangestring7dPreset window.
--from, --toISO 8601 with timezonenoneExplicit window, both required together.
Contract
Authany
Exit codes0 success · 1 generic/API · 2 usage · 3 auth · 5 not found
JSON schemasolwyn.costs.drift.v1

Difference is actual minus estimated. Two caveat lines always print to stderr: the estimate heuristic (server-side, input tokens assumed equal to output), that events without an estimate are excluded and counted separately, that unit-priced and unpriced estimates are null, and that budget-denied events are included. The JSON payload carries the same caveats as a caveats object plus missing_estimate_count.

costs priced-models

The exact provider, model, and modality targets the pricing catalog can bill, stamped with the catalog version. Use it to find a valid --model for simulate.

Terminal
$ solwyn --project proj_0123456789abcdef01234567 costs priced-models
Provider  Model                 Modality  Pricing version
openai    gpt-5                 text      2026-08-06
bedrock   amazon.nova-pro-v1:0  text      2026-08-06
Contract
Authany
Exit codes0 success · 1 generic/API · 2 usage · 3 auth · 5 not found
JSON schemasolwyn.costs.priced-models.v1

No options. The JSON payload records the catalog's provenance as a first-party vendored dataset.

costs simulate

Replay the window's historical usage against one current priced target and compare.

Terminal
solwyn --project <project_id> costs simulate --provider <provider> --model <model> \
  [--region <region> --service-tier <tier>] [--range <preset> | --from <iso> --to <iso>]
OptionTypeDefaultPurpose
--providerprovider enumrequiredTarget provider.
--modelstringrequiredExact model identifier from priced-models.
--regionstringnoneRequired together with --service-tier for Bedrock; rejected for other providers.
--service-tierservice-tier enumnoneRequired together with --region for Bedrock; rejected for other providers.
--range, --from, --towindow7dAs for drift.
Contract
Authany
Exit codes0 success · 1 generic/API · 2 usage · 3 auth · 5 not found
JSON schemasolwyn.costs.simulation.v1
Terminal
$ solwyn --project proj_0123456789abcdef01234567 costs simulate \
    --provider bedrock --model amazon.nova-pro-v1:0 --region us-east-1 --service-tier standard
Metric                       Value
Provider                     bedrock
Model                        amazon.nova-pro-v1:0
Modality                     text
Region                       us-east-1
Service tier                 standard
Baseline                     12.500000
Simulated                    9.750000
Delta (repriced - baseline)  -2.750000
Scanned events               100
Baseline events              95
Repriced events              90
Excluded events              10

Three event populations matter. Scanned is every event in the window. Baseline is the priced, served events whose stored actual cost forms the baseline figure. Repriced is the subset compatible with the target, repriced at current rates. Unpriced and local events are excluded from both figures; events with a modality mismatch or a missing token breakdown stay in the baseline but are not repriced. When the two populations differ, stderr says so explicitly, because the delta then compares different sets. The pricing snapshot date and the approximate-tokenizer caveat also print to stderr.

Simulation is a read-only POST and does not reserve budget, rewrite spend or change billing. Its 25,000-event cap returns 422/exit 2 with no partial result when exceeded. Narrow the window. Definite 401 rejection may refresh JWT once; definite 429 uses the single bounded rate-limit allowance. A 503 or transport failure never automatically replays simulation.

MCP provides list_cost_events, get_cost_baseline, get_unit_economics, get_cost_drift, list_priced_models and simulate_costs in both profiles. get_costs(account=true) requires JWT, rejects explicit project_id, defaults to project grouping and accepts only account-supported filters. MCP pages and deadlines remain bounded.

  • forecast — the month-to-date projection
  • providers — failover groups and unmetered surfaces
  • tags — the tag keys and values you can filter and group by
  • status — budget usage and provider health at a glance
  • Costs — the dashboard's view of the same data
  • Privacy — the complete list of quantities Solwyn transmits, and the content it never does

On this page