> ## Documentation Index
> Fetch the complete documentation index at: https://docs.subscribd.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Multi-Currency Billing

> Bill customers in their local currency across multiple gateways

# Multi-Currency Billing

Subscribd supports per-customer billing currencies. A customer can be billed in EUR while another is billed in USD — on the same account and gateway.

## Gateway support

Not all gateways support multiple billing currencies on a single account:

| Gateway    | Multi-Currency                                  |
| ---------- | ----------------------------------------------- |
| Stripe     | ✅ Yes                                           |
| PayPal     | ✅ Yes                                           |
| Paddle     | ✅ Yes (via storefront currency)                 |
| FastSpring | ✅ Yes (MoR handles it)                          |
| Braintree  | ⚠️ Limited — depends on merchant account config |
| Square     | ❌ No — single currency per location             |

For gateways without multi-currency support, `supportsMultiCurrency()` returns `false`. Attempting to create a subscription in a currency that differs from the gateway's default will throw `SubscriptionException`.

## Setting the billing currency

Override `billingCurrency()` on your `Billable` model:

```php theme={null}
use Pixelworxio\Subscribd\Concerns\ManagesBilling;
use Pixelworxio\Subscribd\Contracts\Billable;

class User extends Authenticatable implements Billable
{
    use ManagesBilling;

    public function billingCurrency(): string
    {
        // Return from a database column
        return strtoupper($this->preferred_currency ?? 'USD');
    }
}
```

The default implementation in `ManagesBilling` reads the currency from the user's most recent active subscription, falling back to `config('subscribd.currency', 'USD')`.

## Currency storage

Each `Subscription` record stores its own `currency` column. Once a customer subscribes in a currency, all subsequent operations on that subscription (charges, refunds, credits) use that same currency.

`Invoice` records store both `total` (minor units) and `currency`.

## The Money value object

Subscribd uses `Pixelworxio\Subscribd\Support\Money` internally to carry amount + currency together:

```php theme={null}
use Pixelworxio\Subscribd\Support\Money;

$price = Money::of(4900, 'USD');   // $49.00
$price->amount;    // 4900 (int)
$price->currency;  // 'USD' (string)

// Comparison
$price->equals(Money::of(4900, 'USD'));   // true
$price->equals(Money::of(4900, 'EUR'));   // false
```

You will encounter `Money` in:

* `BillingGateway::charge()` — accepts a `Money` argument
* `ProcessRefund::execute()` — accepts an optional `Money` argument for partial refunds
* `BillingGateway::refundInvoice()` — receives `?Money $amount`

## Plan currencies

Plans define a base `currency` column. When creating a subscription, the resolved `billingCurrency()` must match the plan currency unless the gateway supports on-the-fly currency conversion.

```php theme={null}
// Plans are defined with a fixed currency
Plan::create([
    'key'      => 'pro-eur',
    'price'    => 4900,
    'currency' => 'EUR',
    // ...
]);
```

If you want to offer the same plan in multiple currencies, create one plan per currency and resolve the right plan for the customer at checkout.

## Credits and currency

Credits are per-currency. A EUR credit cannot be applied to a USD invoice:

```php theme={null}
// Add EUR credit
app(AddCredit::class)->execute($user, amount: 500, currency: 'EUR', description: 'Promo credit');

// Apply to EUR invoice
app(ApplyCreditToInvoice::class)->execute($user, $eurInvoice);

// This does nothing — no EUR credit exists for USD invoice
app(ApplyCreditToInvoice::class)->execute($user, $usdInvoice);
```

`creditBalance(string $currency): int` returns the balance for a specific currency.

## Zero-decimal currencies

Currencies like JPY, KRW, and VND have no minor units. Subscribd handles zero-decimal currencies automatically:

* `Money::of(500, 'JPY')` is ¥500 (not ¥5.00)
* Gateway drivers format amounts accordingly when making API calls

Always store and pass amounts in minor units. The `Money` class handles zero-decimal formatting at the gateway boundary.

## Next steps

* **[Plans](/getting-started/plans)** — Defining plan currencies
* **[Gateways](/gateways/stripe)** — Per-gateway currency support details
* **[REST API](/advanced/rest-api)** — Currency field in API responses
