# Multi-currency

Source: https://developers.swell.is/backend-api/localization/multi-currency

Every store has a base currency, and can enable additional currencies in settings. Each additional currency works in one of two modes: `priced`—you set explicit prices in that currency—or display, where prices are converted automatically from the base currency at the current exchange rate. Exchange rates come from a platform-level table that refreshes hourly.

### Listing enabled currencies

Retrieve the store's currency configuration and current rates from `/:currencies`. Each entry's `type` is `base`, `priced`, or `display`:

```javascript
await swell.get('/:currencies');
```

```json
{
  "base": "USD",
  "rates": {
    "USD": 1,
    "EUR": 0.92,
    "AUD": 1.53
  },
  "config": [
    {
      "code": "USD",
      "rate": 1,
      "name": "US Dollar",
      "symbol": "$",
      "decimals": 2,
      "priced": true,
      "type": "base"
    },
    {
      "code": "EUR",
      "rate": 0.92,
      "name": "Euro",
      "symbol": "€",
      "decimals": 2,
      "priced": true,
      "type": "priced"
    },
    {
      "code": "AUD",
      "rate": 1.53,
      "name": "Australian Dollar",
      "symbol": "A$",
      "decimals": 2,
      "priced": false,
      "type": "display"
    }
  ]
}
```

### Setting per-currency prices

For priced currencies, set explicit values by including a `$currency` object beside the regular fields, keyed by currency code (codes are uppercased automatically):

```javascript
await swell.put('/products/{id}', {
  id: '5ca24abb9c077817e5fe2b36',
  price: 15,
  $currency: {
    EUR: { price: 14 },
    GBP: { price: 12.5 }
  }
});
```

This works at any level where price fields live—the product root, `purchase_options` and their subscription plans, `prices` entries, options, and variants. Fields that support per-currency values are the currency-typed fields on each object, such as `price` and `sale_price`. Write responses always include the full `$currency` map, so you can confirm what is stored.

### Reading prices in another currency

Pass `$currency` on a GET request to have price fields returned in that currency:

```javascript
// Prices flattened to EUR
await swell.get('/products/{id}', {
  id: '5ca24abb9c077817e5fe2b36',
  $currency: 'EUR'
});

// Keep the per-currency map for several currencies
await swell.get('/products/{id}', {
  id: '5ca24abb9c077817e5fe2b36',
  $currency: ['USD', 'EUR']
});
```

The value returned for each price field depends on the currency's configuration:

- Priced currency with an explicit stored value: the stored value is returned.
- Priced currency with no stored value: converted from the base price at the current rate when the currency has fallback conversion enabled; otherwise `null`.
- Display currency: always converted from the base price at the current rate, even if a stored value exists.
- Unconfigured currency code: no error is returned, and prices are left unchanged (or use stored values if any exist for that code).

Converted values are rounded using the currency's settings—`decimals`, and optional rounding to whole units or fraction endings (for example, prices ending in .95). With a single code, the response's `currency` field is set to the requested code and the `$currency` map is omitted; with an array of codes, the map is kept and filtered to the requested codes. `$currency` also applies to records brought in with `expand` and `include`.

### Carts and orders in another currency

To transact in another currency, set the `currency` field on the cart or order—not the `$currency` parameter, which only affects how records are read:

```javascript
await swell.put('/carts/{id}', {
  id: '5cad15bc9b14d1990724663a',
  currency: 'EUR'
});
```

- A priced currency re-prices the cart in that currency—items need a price in it, either stored on the product or passed explicitly on the item.
- A display currency is recorded as `display_currency` while the transaction currency and totals are unchanged—the base currency for a new cart, or whatever currency the cart already transacts in.
- An inactive currency is rejected with an error, and the currency can't be changed after a payment has been made.

When a record's currency differs from the base currency, `currency_rate` is snapshotted at write time and not refreshed by later writes—pass `currency_rate: null` to recompute it at the current rate, or supply your own value.
