Skip to main content
Version: 2.x

PricingEngine

PricingEngine is Bursar's database-free operation-pricing core. It validates the same canonical configuration as the rest of the SDK and prices UsageMetrics events without any store, connection, or facade.

Creating an engine

import { PricingEngine } from "@zonastery/bursar";

const engine = PricingEngine.fromDict(configDict);

fromDict accepts a canonical config document and returns an engine, or throws ConfigError. Unknown fields, undeclared measures or dimensions, invalid matcher types, and unsafe cross-references are rejected at construction. Credit accounting is a fixed Bursar convention rather than a configuration field; plan rank has an authoring default.

Calculating cost

const cost = engine.calculate({
operation: "completion",
measures: { input_tokens: 500, output_tokens: 200 },
dimensions: { model: "gpt-4o" },
});

console.log(cost.total.toString());

calculate(metrics, { rateCard }) prices one event. The optional rateCard key is required when the config contains more than one rate card and the caller has not otherwise selected one (via getRateCardForPlan).

calculateBatch(metrics, { rateCard }) evaluates an array of UsageMetrics with the same rate-card selection and returns CostBreakdown[] in the same order.

getRateCardForPlan(planId) returns the rate-card key referenced by a configured plan — the canonical way to resolve the rate card for a user whose plan is known.

pricingSchema returns the validated, canonicalized config as a plain object.

Example

Using the canonical demo configuration (pricing.operations.completion, rate card standard, per-million-token rates for gpt-4o/gpt-4o-mini, and an expression-based fallback for unmatched models):

import Decimal from "decimal.js";

const engine = PricingEngine.fromDict({
version: 1,
pricing: {
operations: {
completion: {
measures: {
input_tokens: { unit: "token" },
output_tokens: { unit: "token" },
cache_read_tokens: { unit: "token" },
},
dimensions: { model: { type: "string" } },
},
},
rate_cards: {
standard: {
operations: {
completion: {
rules: [
{
when: {
model: { op: "in", values: ["gpt-4o", "gpt-4o-mini"] },
},
charge: {
type: "sum",
components: [
{
type: "per_unit",
measure: "input_tokens",
rate: "0.0025",
unit_size: "1000000",
},
{
type: "per_unit",
measure: "output_tokens",
rate: "0.0100",
unit_size: "1000000",
},
{
type: "per_unit",
measure: "cache_read_tokens",
rate: "0.00125",
unit_size: "1000000",
},
],
},
},
],
unmatched: {
action: "charge",
charge: {
type: "expression",
formula: "input_tokens * 0.005 + output_tokens * 0.015",
},
},
},
},
},
},
},
credits: {},
});

const cost = engine.calculate({
operation: "completion",
measures: { input_tokens: 2_000_000, output_tokens: 500_000 },
dimensions: { model: "gpt-4o" },
});

// Exact decimals: 2,000,000 × 0.0025/M + 500,000 × 0.0100/M = 0.01
const expected = new Decimal("0.0025")
.times(2)
.plus(new Decimal("0.0100").times("0.5"));
if (!cost.total.equals(expected)) {
throw new Error(`unexpected total: ${cost.total.toString()}`);
}
console.log(cost.total.toString()); // "0.01"

UsageMetrics

FieldTypeMeaning
operationstringA key declared in pricing.operations
measuresRecord<string, number | string>Non-negative billable quantities declared by the operation
dimensionsRecord<string, string | number | boolean>Typed values used to select the first matching rate rule
metadataRecord<string, unknown>Caller metadata; it does not participate in pricing

Declared measures omitted by the caller are treated as zero. Required dimensions must be present. Undeclared measures or dimensions are rejected.

CostBreakdown

All monetary fields are Decimal values quantized to six decimal places with half-up rounding. Operation pricing is reported in operationCredits; total is the complete quantized result.

FieldType
operationCreditsDecimal
modelCreditsDecimal
toolCreditsDecimal
searchCreditsDecimal
cacheSavingsDecimal
fixedCreditsDecimal
totalDecimal
breakdownRecord<string, unknown>

See Pricing for how rate cards, rules, and unmatched actions compose, and Expressions for the supported expression operators and functions.