How to implement prepaid credits for an AI product
2026-09-24
To implement prepaid AI credits, accept payment, add value to a customer ledger, reserve enough value before work starts, and settle the actual charge when work ends.
The hard part is keeping those steps consistent when payments retry, requests run at the same time, or a model call fails. A single editable “balance” field is not enough to explain what happened.
Define what the customer buys
Choose whether the balance represents money, tokens, or product credits. State the unit, conversion, expiry, refund terms, and which actions consume it.
A money balance can support several models with different rates. A fixed token budget needs rules for input, output, and model changes. Product credits need a published conversion customers can understand. See credits vs. tokens.
Keep paid and promotional balances separate. They may have different expiry dates, refund rights, and accounting treatment.
Keep an append-only ledger
Record each change as a separate entry with a stable ID. Correct mistakes with linked adjustments rather than deleting history.
Useful fields include customer ID, credit lot, entry type, amount, currency or unit, event time, operation ID, payment reference, price version, and the entry being reversed.
| Entry | Effect |
|---|---|
| Purchase | Adds paid value after the required payment confirmation |
| Promotion | Adds a separate promotional grant |
| Reservation | Holds value while work runs |
| Settlement | Charges actual usage and releases the related hold |
| Release | Removes an unused hold |
| Refund or reversal | Changes the balance with a link to the original entry |
| Expiry | Removes eligible unused value under the published terms |
Store amounts in integers at a defined precision or use exact decimal arithmetic. Avoid floating-point money calculations.
Add credits only once after payment
Use the payment provider's server-side confirmation to fund the account. Do not grant paid credits just because the browser reached a success page.
Verify webhook signatures, match the customer and purchase, and enforce a unique payment reference. A retried webhook should return the existing result rather than add credits again.
Define the action for a refund, dispute, or later payment failure. If the customer has already consumed the balance, record that fact and apply the contract's policy; do not erase the usage.
Reserve value before starting work
Two requests can both see the same available balance. Check the balance and create the reservation in one database transaction using suitable locking or an atomic conditional update.
Available balance = spendable ledger balance − active reservations
For an illustrative account with 100 credits, a request reserves 30. The available balance becomes 70 while that request runs. If the actual charge is 18, settle 18 and release the full 30-credit reservation. The resulting balance is 82, with no remaining hold.
If actual cost can exceed the estimate, either reserve a conservative upper bound, cap the work, or request a further reservation before continuing. State any permitted overage in the customer terms.
A delayed usage meter alone cannot enforce a strict real-time limit. Your service needs a decision before it starts chargeable work.
Settle actual usage once
Give each logical customer operation an ID. Keep it separate from individual provider attempts so you can apply your retry policy correctly.
After work completes:
- Record measured usage and its source.
- Apply the price version agreed for that operation.
- Create one settlement for the operation.
- Release its reservation in the same transaction.
- Return a receipt the customer can reconcile.
Enforce uniqueness for settlement IDs. When a completion message retries, return the prior settlement.
Decide what happens if the model worked but your application lost the response. Provider cost and customer-billable usage are not always identical. Preserve both records and apply the stated failure policy.
Recover from timeouts and missing events
A process can stop after reserving value but before settling it. Use a recovery job to inspect old reservations and determine whether the work completed.
Do not release a hold merely because a timer expired while work may still be running. Confirm the job state or cancel the work first. Otherwise the customer could spend the same value twice.
Keep late usage and manual adjustments visible. An operator should be able to explain every balance change without editing an old ledger row.
Add automatic top-ups carefully
Let the customer set the trigger, top-up amount, and limits. Use a unique top-up attempt ID, and prevent several concurrent low-balance events from charging the card several times.
Show whether a failed top-up pauses work or permits an agreed overage. A payment attempt is not a funded balance.
Reconcile billing and accounting
Reconcile purchases with the payment processor, settlements with usage, and closing balances with the ledger. Keep invoice tax and fees separate from spendable credit value.
Buying credits is a billing event. It does not automatically establish when the seller earns revenue. The accounting guide explains the customer liability and usage entries.
Build it yourself or use a billing platform?
A platform can handle parts of metering, pricing, credit balances, and invoices. Your application still needs to enforce access, define billable work, and handle failures correctly.
Metronome documents prepaid credits, and Orb documents credit-based billing. Validate each product against your exact reservation and settlement needs. See the billing platform comparison.
Test before launch
Run a duplicate payment webhook, two requests that compete for the last credits, a provider timeout, a repeated completion event, and a refund after partial use.
For each case, check the customer's balance, the ledger, the payment record, and the accounting export. The result should be repeatable and explainable.
Learn more about Afternoon
Seamlessly integrated financial stack, that handles your bookkeeping, taxes, and compliance.