| 1 | # Billing, display currency, and cost quotes |
| 2 | |
| 3 | Reasonix keeps three facts separate: |
| 4 | |
| 5 | 1. `original`: an estimate from the selected public/custom rate card in its |
| 6 | pricing-table currency. It is not an invoice or a provider debit. |
| 7 | 2. `valuations`: occurrence-time `identity` and, when available, an |
| 8 | `official_table` estimate for the same model in the other official region. |
| 9 | 3. Wallet balances: the exact original-currency values returned by a provider. |
| 10 | |
| 11 | Reasonix has no runtime FX download, cache, refresh goroutine, or wallet |
| 12 | conversion. Old `fx`/`rateSnapshot` fields remain readable for history only; |
| 13 | new quotes never generate them. |
| 14 | |
| 15 | ```toml |
| 16 | [billing] |
| 17 | display_currency = "auto" # auto | CNY | USD |
| 18 | |
| 19 | [[providers]] |
| 20 | billing_currency = "USD" # pricing-table basis, not settlement currency |
| 21 | billing_mode = "payg" # payg | subscription_equivalent |
| 22 | ``` |
| 23 | |
| 24 | Legacy `[desktop].currency` remains readable and migrates to |
| 25 | `[billing].display_currency`. `auto` is intentionally unresolved in config: |
| 26 | one valid wallet currency may become a tab/session hint; otherwise a single |
| 27 | original currency is selected or mixed currencies are shown as buckets. A |
| 28 | language, browser locale, or host region never changes a rate card. |
| 29 | |
| 30 | ## CostQuote |
| 31 | |
| 32 | `usage.costQuote` is the canonical host-side usage payload: |
| 33 | |
| 34 | | Field | Meaning | |
| 35 | | --- | --- | |
| 36 | | `original` | Original-currency rate-card estimate | |
| 37 | | `originalTotals[]` | ISO-sorted original buckets for mixed aggregates | |
| 38 | | `valuations.*.basis` | `identity` or `official_table` for new quotes | |
| 39 | | `selected` | A single amount only when a display total exists | |
| 40 | | `costComplete` | Usage and pricing facts are complete | |
| 41 | | `displayComplete` | A requested single-currency total exists | |
| 42 | | `complete` | Compatibility alias mirroring `displayComplete` | |
| 43 | | `displayStatus` | `matched`, `fallback_original`, `bucketed`, or `unavailable` | |
| 44 | | `aggregateMode` | `single_currency`, `common_valuation`, or `currency_buckets` | |
| 45 | | `rateBand` | DeepSeek occurrence-time band: `peak`, `off_peak`, or aggregate `mixed` | |
| 46 | | `ratedAt` | UTC request-completion time used to select a scheduled rate | |
| 47 | |
| 48 | If a requested currency is unavailable but every original is the same, the |
| 49 | original amount is shown with `fallback_original`. Mixed originals produce |
| 50 | `originalTotals` and no scalar zero. `—` is reserved for missing usage or |
| 51 | pricing (`unavailable`). Legacy scalar aliases (`cost`, `costUsd`, |
| 52 | `total_cost`) are written only when `selected` exists. |
| 53 | |
| 54 | ## DeepSeek scheduled rates |
| 55 | |
| 56 | For official DeepSeek OpenAI, Responses, and Anthropic endpoints, Flash and V4 |
| 57 | Pro use occurrence-time pricing. Peak windows are 09:00–12:00 and 14:00–18:00 |
| 58 | Beijing time; boundaries are left-closed/right-open and all other times are |
| 59 | off-peak. The request-completion timestamp is used because the provider does not |
| 60 | report per-token billing time. Images sent to a vision-capable model are billed |
| 61 | as input tokens from provider usage. |
| 62 | |
| 63 | Two dated schedules are recorded. From 2026-08-17 00:00 Beijing time, V4 Flash, |
| 64 | `deepseek-v4-flash-vision-exp` (same list price as Flash), and V4 Pro. From |
| 65 | 2026-09-10 12:00 Beijing time, `deepseek-flash` carries a lower Flash price, and |
| 66 | the retired `deepseek-v4-flash` and `deepseek-v4-flash-vision-exp` ids are served |
| 67 | by that model and billed at the same rate. V4 Pro keeps its own price until the |
| 68 | vendor routes it to V4.1 Flash. A quote resolves against the schedule in effect |
| 69 | at its occurrence time, so the superseded August rates stay queryable. |
| 70 | |
| 71 | The stored provider price remains the peak anchor. Dynamic resolution is |
| 72 | enabled only for PAYG configurations whose complete rate card exactly matches an |
| 73 | official anchor. A config that still holds the previous generation's anchor is |
| 74 | recognized as an untouched official row and billed against the live schedule, |
| 75 | so a dated vendor price change reaches it without a re-save. Custom endpoints, |
| 76 | edited prices, and unrecognized models remain static. Persisted session, ledger, |
| 77 | and stats quotes are never repriced. |
| 78 | |
| 79 | ## Wallets and diagnostics |
| 80 | |
| 81 | Wallets are never converted or cross-added. An explicit target uses the exact |
| 82 | matching wallet; if it is absent, the real currency is shown with an ISO |
| 83 | prefix. Automatic mode uses a single valid wallet currency only as a runtime |
| 84 | hint. Multiple/unknown/error responses do not affect the cost facts. |
| 85 | |
| 86 | ```sh |
| 87 | reasonix doctor billing |
| 88 | reasonix doctor billing --json |
| 89 | ``` |
| 90 | |
| 91 | The compatible `fx` report is always `enabled=false` and has no cache. The |
| 92 | report also lists the automatic selection policy, pricing-table currencies, |
| 93 | and official-catalog matches. |
| 94 |