packstub / credits
Credits and usage metering for Laravel: per-user or per-team balances, credits that expire and are spent soonest-expiring first, holds you reserve before an AI call and settle once its cost is known, fractional meters that never round a credit away, plan allowances renewed without a cron, idempotenc
Fund package maintenance!
Requires
- php: ^8.4
- laravel/framework: ^13.0
Requires (Dev)
- laravel/pint: ^1.13
- orchestra/pest-plugin-testbench: ^5.0
- orchestra/testbench: ^11.2
- pestphp/pest: ^5.1
- pestphp/pest-plugin-laravel: ^5.0
- phpunit/phpunit: ^13.3
Suggests
- packstub/agents: Charge AI turns in credits: hold before the turn, settle on the token usage through the meters.
- packstub/filament-features: Plans and limits per tenant: hand each plan's monthly credits to Credits::allowancesUsing().
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-28 09:56:11 UTC
README
Credits and usage metering for Laravel apps that charge per use: AI features, exports, SMS, API calls. Give each user or team a balance, let plans top it up every month, charge measured usage, and know, at any time, where every credit came from and where it went.
$team->credits()->grant(1_000, 'Pro plan', expiresAt: now()->endOfMonth()); $hold = $team->credits()->hold(200, 'AI turn'); // reserve before the call $response = $agent->prompt($question); $hold->settleUsage([ // charge what it actually cost 'ai.input_tokens' => $response->usage->uncachedInputTokens(), 'ai.output_tokens' => $response->usage->outputTokens, ]); $team->credits()->available(); // whole credits; a fraction carries to the next call
Features
- Holds for AI calls: reserve an estimate before the call, settle what it cost after; a dead worker leaks nothing.
- Credits that expire, spent in order: every grant is a lot with its own expiry, taken soonest-expiring first.
- Meters with exact fractions: 400 tokens at 1 credit per 1,000 charge nothing yet; the remainder carries to the next call.
- Plan allowances without a cron: granted once per period on first use, however many workers race; anchored or calendar.
- Idempotency keys: a retried job or webhook never charges twice; a reused key for a different request is an error.
- Refunds and transfers: credits go back to the lots they came from, or move to another wallet, keeping their expiry.
- Upgrades, rollover, rates per plan: a bigger plan grants the difference at once; quotes before charging.
- Reporting from the ledger: what expires when, the balance at any moment, credits spent and usage per period.
- Books that balance: append-only lines, row locks, and
credits:auditto prove every cached number from the rows under it.
Integer credits throughout (pick your scale: 1 credit = 1/1000 of a cent works), no floats, SQLite, MySQL, MariaDB and Postgres.
Compatibility
| Credits | Laravel | PHP |
|---|---|---|
| 1.x | 13.x | 8.4+ |
Installation
composer require packstub/credits php artisan migrate
Add the trait to whatever holds credits:
use Packstub\Credits\Concerns\HasCredits; class Team extends Model { use HasCredits; }
Schedule the catch-up for idle wallets (optional: every wallet catches up when it is used):
Schedule::command('credits:expire')->hourly();
Documentation
- Installation and configuration
- Wallets, lots and spending: grants, expiry, idempotency, refunds, transfers, adjustments, reporting, events, exceptions
- Holds and AI calls: reserve, settle, release, extend, late settles, expiring credits, a laravel/ai recipe
- Meters: usage priced in credits with exact fractions, quotes, rates per plan
- Allowances: plan credits every period, anchored or calendar, upgrades, rollover
- Selling credits: top-ups with Cashier (Stripe, Paddle), plan credits, refunded payments
- Auditing and concurrency:
credits:audit, row locks, SQLite in production
Testing
composer test
Security
Report vulnerabilities to security@packstub.dev, not through a public issue: see SECURITY.md, which also lists what to keep on your side of the line (wallets from the authenticated holder, holds and transactions looked up through the wallet, quantities from the provider's response).
License
MIT. See LICENSE.md.
