Skip to main content
Inspect and reconcile the billing rate card that turns recorded provider cost into a billable price.

Synopsis

voicegw prices is the command group for VoiceGateway’s rating layer. The rate card maps recorded cost to a billable price and stamps that price immutably onto every request row (rated_price_usd + rate_rule). The card has two layers: the rate_card: seed in voicegw.yaml plus DB overrides you set at runtime with set (one store, both surfaces). ls prints the effective card (seed + overrides), reconcile rolls up rated revenue against recorded cost per tenant, sync checks fixed-price rules against the current base cost, and set / rm edit the DB overrides. The full model (cost-plus vs fixed, tenant->plan->global resolution, write-time immutability) lives at Rating.

voicegw prices gaps

Models that have run and cannot be priced, heaviest first. This is the work list for operator-declared pricing: which models still need a rate typed in, ordered by how much traffic is currently going unpriced, so the task is finite rather than discovered one dashboard row at a time. The gap column names which of two problems each row has, because the remedies differ:
  • not in catalogvoice-prices does not carry the model. It needs a catalogue entry, or an operator rate.
  • matched, no rate — the catalogue matched the model and holds no rate for it. deepgram/nova-general matches the entry nova, whose price fields are empty. The entry exists already and only needs a rate put on it, so these are usually the cheapest gaps to close.
Only billable rows count: non-error requests that moved units. End-of-utterance rows carry no model and an empty pricing source, and would otherwise dominate the list with something nobody can put a price on.
Rows whose model matched the catalogue but carried no rate were recorded as priced before v0.25.6, so a window spanning that release under-reports the matched, no rate column.

Usage

voicegw prices ls

Print the rate card in effect: the default markup followed by a table of rules. Each row shows the rule’s scope (provider/model (modality)), tenant, plan, kind (cost_plus or fixed), and the audit token that will be stamped onto matching requests (for example cost_plus:1.3 or fixed:0.006/minute). When the card has no rules, every request bills at the default markup and the table is skipped.

Options

Example

voicegw prices reconcile

Roll up rated revenue against recorded cost per tenant over a window, then flag tenants whose margin is thin (under the --threshold percent of rated revenue) or negative. This is the margin health check for a billing cycle: a tenant that is losing money or barely breaking even becomes visible before the invoice goes out.

Options

Prerequisites

  • Cost tracking enabled in voicegw.yaml (the SQLite backend must be configured, or the command exits with 1).

Output

A table with one row per tenant: tenant, requests, cost, rated, margin, margin %, and a flag. The flag is ok, thin (yellow), or NEGATIVE (red). When the window has no billable usage, the command prints No billable usage in the window. instead of a table.

Example

voicegw prices sync

Check each fixed (/unit)ruleagainstthecurrentvoicepricesbasecostforoneunit,andflagruleswhosemarginisthin(underthreshold)ornegative.Afixedruleadvertisesaflat/unit) rule against the current voice-prices base cost for one unit, and flag rules whose margin is thin (under `--threshold`) or negative. A fixed rule advertises a flat `/unitthat is decoupled from the base cost, so when the base moves the rule can silently cross into a loss.cost_plus` rules auto-follow the base and need no sync, so they are not listed. Per-unit base cost is resolvable only for concrete-model STT (minute / second) and TTS (char / 1k_char) rules. Token and request blends (and wildcard-model rules) report unresolvable because there is no single per-unit base to compare against.

Options

Output

A table with one row per fixed rule: scope, unit, fixed price, base cost, margin, margin %, and a flag (ok, thin, NEGATIVE, or unresolvable). When the card has no fixed rules, the command prints No fixed rules to sync; cost-plus rules auto-follow the base price. instead of a table.

Example

voicegw prices set

Upsert a DB rate-card override for a scope. Overrides layer on top of the rate_card: seed in voicegw.yaml, and a DB override wins a tie against a seed rule at the same scope. One rule per scope: setting the same scope again updates it in place (the scope is tenant|plan|modality|provider|model). Requires cost tracking enabled. A rule is either cost-plus (--markup) or fixed (--fixed + --unit), never both.

Options

Example

voicegw prices rm

Remove the DB override for a scope, using the same scope flags as set. Exits non-zero if there is no override at that scope.

Example

Examples

Verify fixed rules still hold their margin after a pricing refresh

Exit codes

The gateway rebuilds the effective card (seed plus DB overrides) on startup and on config refresh, so a running server picks up set / rm changes the next time its config refreshes. The same DB overrides can also be edited over HTTP (POST / DELETE /v1/billing/rate-card/rules) or from the dashboard (Configure -> Rate card).
voicegw reconcile | voicegw costs

See also

  • Rating: the rating layer end-to-end (cost-plus vs fixed, resolution, write-time immutability).
  • voicegw.yaml reference: the rate_card: config block these commands read.
  • HTTP API Reference: the GET /v1/billing/usage and GET /v1/billing/rate-card endpoints fed by the same rating layer.