/adjustments
// import { flatCredit, minimumCommit, volumeTrueUp } from "pricemeter/adjustments";// Period close: $100 minimum commitment, $30 spent → charge the $70 shortfall.const plan = minimumCommit({ account: "acme", minimumMicroUsd: 100_000_000, spentMicroUsd: 30_000_000, // e.g. sqliteAdapter.spent({ account, from, to }) period: "2026-09", at: Date.parse("2026-10-01T00:00:00Z"),});// plan.ledger → [{ op: "charge", amount: 70000000, refType: "period", refId: "minimum_commit:acme:2026-09" }]await metering.commit(plan); // { ok: true } — and again on a retried cron: still one row
flatCredit({ account: "acme", amountMicroUsd: 10_000_000, refType: "coupon", refId: "WELCOME10:acme", at });// → one charge of −10000000pricemeter/adjustments is a set of pure functions that return a Plan; you write it with metering.commit(plan) (A92). When they run (cron, period close) is your application’s decision. Its seam in the module test is “producing plan items”.
| API | Plan | refId |
|---|---|---|
minimumCommit({ account, minimumMicroUsd, spentMicroUsd, period, at, refType? }) |
One charge for the shortfall (minimum − spent) if any; otherwise an empty plan |
minimum_commit:{account}:{period} (A103), refType defaults to "period" |
flatCredit({ account, amountMicroUsd, refType, refId, at }) |
One negative charge (a coupon-like credit, B27) |
yours |
volumeTrueUp({ account, meter, dims?, rate, quantity, chargedMicroUsd, refType, refId, at }) |
The whole period priced at the tier it ended in; the difference as a charge + usage row (quantity: 0, detail.adjustment: true) |
yours |
const rate = defineRate({ model: "volume", tiers: [{ from: 0, unitPriceMicroUsd: 10_000 }, { from: 1_000, unitPriceMicroUsd: 8_000 }] });// 900 then 200 units were charged at the tier each landed in: 9,000,000 + 1,600,000volumeTrueUp({ account: "acme", meter: "api", rate, quantity: 1_100, chargedMicroUsd: 10_600_000, refType: "period", refId: "true_up:api:2026-09", at });// → ledger [{ op: "charge", amount: -1800000 }], usage [{ quantity: 0, amount: -1800000, detail: { adjustment: true, … } }]volumeTrueUp pairs with adjustmentTiming: "none": during the period each observation pays the tier it lands in, and the period is corrected once at the end (B6). The period total is not one observation, so perObservation clamps do not apply. With on_crossing the same correction happens immediately, with the observation (volume adjustment).
You supply the spend: e.g. sqliteAdapter.spent({ account, from, to }) returns the sum of charge + capture in the period window.
How you’d do it without this
Section titled “How you’d do it without this”A plan is just two lists; you can build it by hand:
// Without /adjustments: it is just a Plan. What matters is the stable refId.const shortfall = 100_000_000 - 30_000_000;const byHand: Plan = { ledger: shortfall > 0 ? [{ op: "charge", account: "acme", amount: shortfall as never, refType: "period", refId: "minimum_commit:acme:2026-09", at }] : [], usage: [],};await metering.commit(byHand);The only thing that matters is a stable refId: a cron that closes the same period twice must produce a second plan that is a no-op in commit. Put the account in the refId: ledger uniqueness on (op, refType, refId) spans accounts, and an account-less refId silently drops the second account’s item.