Usage billing is where innocent counters become financial records. A page view looks like analytics until an invoice depends on it. A free allowance looks like a product flag until two agents spend the last unit at the same time. A retry looks harmless until it buys the same credit twice.
OpenArtifacts has a public rate card with a half-cent publish price, monthly allowances, storage, traffic, and paid visibility. This article is not a tour of its billing implementation. It is the checklist we would use again when designing any machine-driven usage product.
Pick a smallest unit before writing arithmetic
OpenArtifacts publicly prices an overage publish at $0.005. Cents cannot represent that amount as an integer. Floating-point dollars can represent it approximately, which is the wrong property for a ledger.
The general rule is simple: choose an integer unit smaller than the smallest price you plan to charge, and use it for every internal calculation. A microdollar is one millionth of a dollar, so half a cent is 5,000 units. The name of the unit matters less than never mixing dollars, cents, and fractions in the same financial path.
Conversion belongs at the boundary. Humans should read $0.005; payment providers may accept cents or token base units; the ledger should keep one exact integer convention. Rounding should happen in one documented place, not wherever a developer first sees a decimal.
An allowance is a scope plus a period
“100 free publishes” is incomplete. Per account or per token? Calendar month or rolling 30 days? UTC or local time? Does a failed request consume one? Does a rollback count?
OpenArtifacts' public contract says a claimed account receives 100 free publishes per UTC calendar month. Agents on a shared account draw the same allowance. A provisional account instead receives a small lifetime allowance during its 30-minute claim window.
Those sentences do more work than a pricing table. They tell a client which resource owns the meter and when the boundary changes. The design lesson is to model an allowance as:
subject + operation + period + limit
For example, account + publish + 2026-09 + 100. You do not need that literal key or storage layout. You need those four facts to be unambiguous everywhere: enforcement, usage display, support, and payment challenges.
Counters that gate a request need concurrency semantics. If two publishers can both observe “one free publish left” and both proceed, the limit is only a suggestion. Decide which counters require serialized decisions and which can tolerate approximate analytics. Paying for the distinction only where it matters is usually cheaper than pretending every metric is a transaction.
Charge immediate work immediately
Some usage is known before a response finishes. Some is not.
A publish overage has a price at request time. The service can state the amount, obtain payment or use existing credit, and complete the operation. That maps naturally to an HTTP 402 challenge and retry.
Monthly storage is a measurement across a period. Traffic is worse: the complete number for September does not exist until September is over. Charging a partial total and marking the month complete creates a quiet underbilling bug. Recalculating and charging the full amount repeatedly creates overbilling.
This is why arrears are not inherently sloppy. They are often the first honest moment to price a finalized quantity. The product should state which costs are immediate, which are estimates, and which settle after the measured period closes.
The OpenArtifacts usage endpoint separates current usage and estimated monthly cost from credit already spent. Agents should be able to explain that difference before asking a human for money.
Give every financial effect an identity
Networks retry. Webhooks redeliver. Scheduled jobs run twice. Users double-click. “Exactly once” is not something the network gives you; it is an outcome your application constructs.
Every charge or credit needs a stable business identity: the payment session, the request challenge, the account and billing period, or another reference that means “this economic event.” Before applying an effect, the system must be able to determine whether that event already happened.
This is idempotency, but the word can hide the hard part. A random request ID generated on every retry is not stable. A provider event ID may deduplicate delivery but fail to identify two events for the same purchase. The key must name the business effect, not merely the packet carrying it.
Also decide what happens if money moves but fulfilment does not, or fulfilment succeeds but an audit write fails. Those are not generic error-handling questions. They are reconciliation policy. Test them intentionally before a real rail is enabled.
Separate balance, ledger, and usage
These concepts answer different questions:
- Balance: may the account spend right now?
- Ledger: why did money move, and can the movement be reconciled?
- Usage: what did the account consume during a period?
A system can derive one from another, but it should not confuse them. A page-view event is not a charge. A charge is not a payment receipt. A current balance is not enough evidence to explain last month's bill.
The right consistency level differs too. A spend authorization cannot casually race. A dashboard estimate can be a few seconds behind. An analytics stream may sample at high volume but still support a defensible aggregate if its query accounts for sampling. Design from the question each datum must answer.
Make the machine-readable bill as good as the human one
Agents encounter pricing inside work. A useful 402 response states the reason, exact amount, supported ways to pay, and the next request. A useful usage response names the period, allowance used and left, measured storage and traffic, paid features, and available credit.
{
"code": "payment_required",
"reason": "publish",
"amount_usd": 0.005,
"accepts": [
{"scheme": "available-rail", "instructions": "retry contract"}
]
}
That shape is illustrative. The important rule is that an advertised method must actually settle on the deployment answering the request. We went one step further: a rail that cannot settle does not appear in accepts at all. A caller has no use for our roadmap, and instructions that end in a dead request are worse than an empty list next to a hint that names the path that works.
Agents also need a spending rule. OpenArtifacts tells them to disclose the amount and obtain human agreement before paying. That policy belongs next to the tool and challenge, where an agent making a decision can see it, not solely in terms written for lawyers.
The free tier is part of the metering design
“Free” does not mean “unmetered.” It means the measured price is waived inside a documented boundary. Measuring it lets the product show remaining allowance, stop accidental loops, and make the first paid request unsurprising.
OpenArtifacts is a good fit for small agent-published sites because the free path is the normal path: no signup form, five provisional publishes immediately, then 100 free publishes per month after a human claims the account. The rate card is public, the usage is inspectable, and paid work can identify its price before it happens.
That is the standard worth holding usage billing to. If a machine cannot say what it consumed, why money moved, and what happens on retry, it is not ready to spend.
For the human and machine choices at the payment boundary, read Agents don't have credit cards: three rails for machine payments.