Model pricing API
Lookup material for the endpoints that apply a saved model price to past requests that were priced at the fallback rate. They change stored audit events only. Budget, session and virtual-key spend counters are never changed.
Endpoints
Both endpoints use POST and return JSON.
| Endpoint | Purpose |
|---|---|
/api/v1/ui/settings/model-costs/reprice/preview | Counts the requests an apply would update and estimates the spend change. Writes nothing. |
/api/v1/ui/settings/model-costs/reprice | Updates requests in one bounded call and reports how many remain. |
Authorization
Both endpoints accept only admin tokens. Viewer, builder and developer tokens receive 403, and a request with missing or invalid credentials receives 401. The price is never taken from the request: it is the entry for the model that is saved in the model pricing table.
Preview
The request body has model (the model ID exactly as it appears in the pricing table) and days (the look-back window ending now, default 7, maximum 365).
| Response field | Meaning |
|---|---|
model | The model ID. |
from, to | The exact window the preview used. Send them back to the apply endpoint so its counts match the preview. |
events | Requests of the model in the window that were priced at the fallback rate and have a recorded cost above zero. |
firstSeen, lastSeen | The earliest and latest of those requests, or null when events is 0. |
oldCostUSD | The recorded cost of those requests. |
newCostUSD | The cost of the same requests at the saved price. |
deltaUSD | newCostUSD minus oldCostUSD. |
oldPrice, newPrice | The fallback price and the saved price, each as promptPer1M, completionPer1M, cacheReadPer1M and cacheCreationPer1M. |
A model with no saved price receives 409.
Apply
The request body has model, from and to (RFC 3339 timestamps, normally copied from the preview), and newPrice (the newPrice object from the preview). If the saved price no longer equals newPrice, the call is refused with 409 so that every batch uses the price that was previewed; preview again to continue. The saved price is checked again inside every batch, so a price saved while a call is running stops it at the next batch: the response is 409 with changed set to the number of requests updated before it stopped, and those requests keep the price they were updated with. The window must be at most 365 days, must end no later than one minute from now, and from must be before to. Otherwise the response is 400.
Each call updates up to a bounded number of requests, then returns:
| Response field | Meaning |
|---|---|
changed | Requests updated by this call. |
remaining | Requests in the window still priced at the fallback rate after this call. |
done | true when remaining is 0. Repeat the call while it is false. |
oldCostUSD, newCostUSD | The recorded and the new cost of the requests this call updated. |
Each updated request gets the cost at the saved price and cost-table as its pricingSource. A request that already has cost-table is never selected again, so a repeated call, a concurrent call from another session or replica, and a call after the work is finished are all safe: they change nothing that was already changed, and the last returns changed of 0.
The cost totals that the Cost views read are adjusted in the same transaction as the requests, so a view never shows a total that disagrees with the updated requests.
Audit entry
A call that updates at least one request records a configuration audit entry with action model_price.applied_to_past_requests, in the same transaction as its last batch. It carries the actor, the model, the window (windowFrom, windowTo), the fallback and new prices, the cost before and after, and rowsChanged. A call that changes nothing records no entry.