---
title: "The Credits facade — Credits for Laravel | Roundly"
description: "Credits::for($owner) — an immutable scope to add, deduct, set and read credits per bucket, as integers or Money, plus owner-free helpers."
url: https://roundly-consulting.com/open-source/docs/credits-for-laravel/facade
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Credits for Laravel](https://roundly-consulting.com/open-source/docs/credits-for-laravel.md)

# The Credits facade

RoundlyConsulting\\Credits\\Facades\\Credits (also auto-registered as the global alias Credits) is the recommended entry point. Credits::for($owner) returns an immutable scope: bucket() and allowOverdraft() each return a new scope, so you can keep one and reuse it:

```php
use RoundlyConsulting\Credits\Facades\Credits;
use RoundlyConsulting\Money\Money;

Credits::for($user)->add(100, 'Welcome');                       // Credit row
Credits::for($user)->deduct(30, 'Order #42', ['order_id' => 42]); // InsufficientCreditsException below the floor
Credits::for($user)->modify(-5);                                 // a signed change
Credits::for($user)->allowOverdraft()->deduct(500);              // may go below the floor
Credits::for($user)->setTo(0, 'Reset');                          // one delta row; null when already there

Credits::for($user)->balance();                                  // int — the default bucket
Credits::for($user)->balance(now()->subWeek());                  // as of a point in time
Credits::for($user)->has(50);                                    // bool
Credits::for($user)->total();                                    // int — every bucket

$points = Credits::for($user)->bucket('points');
$points->add(100, 'Welcome');
$points->balance();                                              // 100

Credits::for($user)->buckets(['promotional', 'purchased'])->balance(); // summed, read-only
Credits::for($user)->buckets(['promotional', 'purchased'])->has(50);

// A currency-denominated bucket reads and writes Money:
$store = Credits::for($user)->bucket('store_credit');
$store->addMoney(Money::ofMajor('25.00', 'EUR'), 'Gift card');
$store->deductMoney(Money::ofMinor(1050, 'EUR'), 'Order #42');
$store->money();                                                 // Money EUR 14.50
$store->currency();                                              // Currency EUR
$store->format();                                                // "14.50"
$store->formatMoney('en');                                       // money's locale formatter (symbol + amount)

// Owner-free helpers:
Credits::format(1250, scale: 2);                                 // "1250.00" at credits.scale = 0
Credits::currency('store_credit');                               // ?Currency
```

add() and deduct() take a non-negative amount and throw InvalidArgumentException otherwise — use modify() for a signed change. The same holds for addMoney(), deductMoney() and modifyMoney(). buckets(\[...\]) only reads, because every write names exactly one bucket.

## Scope methods

| Method | Returns | What it does |
| --- | --- | --- |
| `bucket($name) / allowOverdraft($allow = true)` | CreditsScope | A new scope in that bucket / allowed below the floor. |
| `buckets($names)` | CreditBuckets | A read-only sum of several buckets — balance($at) and has($amount, $at). |
| `add($amount, $description, $meta)` | Credit | Grant a non-negative amount. |
| `deduct($amount, $description, $meta)` | Credit | Take a non-negative amount off; guarded by the floor. |
| `modify($amount, $description, $meta)` | Credit | A signed change — positive grants, negative deducts. |
| `setTo($amount, $description, $meta)` | ?Credit | One delta row to an exact balance; null when it already matches. |
| `balance($at) / has($amount = 1, $at)` | int / bool | The scoped bucket’s balance, optionally as of a point in time. |
| `total($at)` | int | Every bucket of the owner, whichever bucket is scoped. |
| `currency()` | ?Currency | The bucket’s currency, or null for plain credits. |
| `money($at)` | Money | A denominated bucket’s balance as Money. |
| `addMoney() / deductMoney() / modifyMoney()` | Credit | The Money forms of add(), deduct() and modify(). |
| `format($scale, $rounding, $at)` | string | The balance as a locale-free decimal string (a denominated bucket at its exponent). |
| `formatMoney($locale)` | string | A denominated bucket’s balance through money’s locale formatter. |

## Flat methods

The facade also exposes the flat verbs every scope ends in — handy for jobs that already hold a CreditChangeData:

| Facade / manager method | Returns | Action | Notes |
| --- | --- | --- | --- |
| `for($owner)` | CreditsScope | — | The entry point for one owner. |
| `format($amount, $scale, $rounding, $storedScale)` | string | `FormatCreditsAction` | Needs no model. |
| `currency($bucket)` | ?Currency | `ResolveBucketCurrencyAction` | null = plain credits. |
| `balance($owner, $bucket, $at)` | int | `GetCreditsBalanceAction` | One bucket. |
| `total($owner, $buckets, $at)` | int | `GetCreditsTotalAction` | null = every bucket; the list is de-duplicated; \[\] is 0. |
| `modify($owner, CreditChangeData $data)` | Credit | `ModifyCreditsAction` | Signed; overdraft-guarded; fires CreditsModified. |
| `setTo($owner, $amount, $description, $meta, $allowOverdraft, $bucket)` | ?Credit | `SetCreditsAction` | One delta row; null when it already matches. |
| `fake()` | CreditsFake | — | Static, on the facade — see Testing. |

The HasCredits model methods ($user->modifyCredits(), $user->creditsBalance(), …) are shorthand for the same calls — each goes through Credits::for($user), so they behave exactly like the facade and the fake records them.

## Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

[More ways to support, including crypto](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/credits-for-laravel.md)
