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.