Synopsis
voicegw reconcile reads VG’s per-request log records for a date window, parses an operator-supplied normalized provider usage file, and produces a per-model diff with absolute and percent differences. The full workflow (when to reconcile, how to interpret the diff, expected drift per modality) lives at Cost Reconciliation.
The provider-side input file format is documented per provider at Reconcile File Formats.
Usage
Options
Prerequisites
- Cost tracking enabled in
voicegw.yaml(the command exits with 1 otherwise). - A provider usage file in VG’s canonical schema (one schema per provider; see Reconcile File Formats).
Output
Text (default)
An aligned table with one row per model. Columns: model, VG units, provider units, units delta%, VG cost, provider cost, cost delta$, cost delta%. Rows whose absolute cost diff % exceeds--threshold are tagged with a trailing * and rendered in ANSI yellow when stdout is a TTY (no color when piped or captured). Models present in only one side carry a (no vg data) or (no provider data) suffix instead.
A Total row sums VG cost and provider cost across rows where both sides matched (missing-side rows are excluded so their $0 placeholders do not skew the total). When any rows are flagged, a footer line (N flagged row(s) marked with *) follows, and then a What to check section naming what each disagreement is about.
What to check
A diff on its own says something is wrong, not what. That matters most when rates are operator-entered: a rule typed as0.008 instead of 0.08 produces a perfectly plausible bill, and the provider invoice is the only thing in the world that can catch it.
Each flagged row is diagnosed as one of three causes, because they have three different fixes and only one is in your hands:
For a
rate disagreement the report names which authority produced VG’s figure and what the invoice implies the rate should be:
rule_id rather than by its price, because two rules at different scopes can carry the same rate and restating the number identifies nothing. When the catalogue produced the figure instead, the report says so: that is not a rule to edit, it means the published rate is stale or your contract differs from list, and the remedy is to declare a cost rule rather than to change one.
The unit label adapts to the provider:
tokensfor OpenAI (input + output, summed).audio_sfor Deepgram (seconds; VG-side minutes are converted at the boundary).charsfor Cartesia.
CSV
Sixteen columns:model, vg_units, provider_units, units_diff_abs, units_diff_pct, vg_cost_usd, provider_cost_usd, cost_diff_abs, cost_diff_pct, matched_in_vg, matched_in_provider, flagged, cause, pricing_sources, vg_rate, provider_rate. The flagged column is True/False so spreadsheets can filter on it without re-deriving the threshold comparison, and cause carries the same diagnosis the text report explains, so a machine reader gets it too. pricing_sources is pipe-separated when a model was priced by more than one authority over the window.
JSON
A nested document matching design §2.2:total sums only rows where both sides matched (missing-side rows excluded, mirroring the text format). flagged_count counts rows where flagged=True. Useful for piping into a monitoring or alerting tool.Examples
Diff May 2026 OpenAI usage
JSON output for piping
Cartesia with the JSON variant of the canonical file
Exit codes
Related
voicegw export-costs | voicegw costs
See also
- Cost Reconciliation: when to reconcile, how to interpret the diff, per-modality drift tolerance.
- Reconcile File Formats: per-provider schemas this command expects.