Regions, currencies, locales

Catalog-context primitives a storefront resolves at boot: regions feed the pricing context (region_id → region currency), currencies tell you what the store has enabled, locales drive the language switcher and the client's x-locale header. All reads are anonymous. Money is EUR decimal major units everywhere.

SDK module: @barter/storefront/api/regions.


GET /api/store/regions

  • Purpose — list the store's regions; a storefront usually picks one at boot (or by shopper choice) and passes its id/currency as the pricing context on catalog reads.
  • Auth — anon: x-client-id required.
  • RequestGET /api/store/regions
// query (all optional)
{
  "q": "bulg",             // case-insensitive substring on name
  "currency_code": "eur",  // exact match, lowercased server-side
  "limit": 50,             // 1–200, default 50
  "offset": 0
}
  • Response — ordered by name. NOTE: Cartbase regions carry NO embedded countries array (divergence from Medusa's Store API — country/tax scope lives server-side in tax_regions).
{
  "regions": [
    {
      "id": "reg_01tst000000000000000000001",
      "name": "Bulgaria",
      "currency_code": "eur",       // lowercase — feeds the pricing context
      "automatic_taxes": true,
      "metadata": null,
      "created_at": "2026-07-01T00:00:00.000Z",
      "updated_at": "2026-07-01T00:00:00.000Z"
    }
  ],
  "count": 1,
  "offset": 0,
  "limit": 50
}
  • Working curl
REGIONS=$(curl -sf "$BASE/api/store/regions" -H "x-client-id: $CLIENT_ID")
echo "$REGIONS" | grep -q '"regions"'
echo "$REGIONS" | grep -q '"count"'
REGION_ID=$(echo "$REGIONS" | grep -o '"id":"reg_[^"]*"' | head -1 | cut -d'"' -f4)
test -n "$REGION_ID"
  • Errors — 400 missing_client_id (header absent/empty), 400 validation_failed (bad limit/offset).
  • SDKlistRegions(client, query?).
  • Components — region/currency selector (see components.md).
  • Settings — Admin → Settings → Regions.
# Auth contract: no x-client-id → 400 missing_client_id
STATUS=$(curl -s -o /dev/null -w '%{http_code}' "$BASE/api/store/regions")
test "$STATUS" = 400
curl -s "$BASE/api/store/regions" | grep -q '"code":"missing_client_id"'

GET /api/store/regions/:id

  • Purpose — retrieve one region (e.g. re-hydrate the shopper's stored choice).
  • Auth — anon: x-client-id required.
  • RequestGET /api/store/regions/{region_id} — no query.
  • Response{ "region": { ...same shape as the list rows... } }
  • Working curl
REGION=$(curl -sf "$BASE/api/store/regions/$REGION_ID" -H "x-client-id: $CLIENT_ID")
echo "$REGION" | grep -q '"region"'
echo "$REGION" | grep -q '"currency_code"'
  • Errors — 404 not_found (unknown id, soft-deleted, or another tenant's region — invisible, not forbidden).
STATUS=$(curl -s -o /dev/null -w '%{http_code}' \
  "$BASE/api/store/regions/reg_doesnotexist$RUN" -H "x-client-id: $CLIENT_ID")
test "$STATUS" = 404
curl -s "$BASE/api/store/regions/reg_doesnotexist$RUN" \
  -H "x-client-id: $CLIENT_ID" | grep -q '"code":"not_found"'
  • SDKretrieveRegion(client, regionId).
  • Components — region/currency selector.
  • Settings — Admin → Settings → Regions.

GET /api/store/currencies

  • Purpose — list the currencies ENABLED on this store (the shared currency catalog filtered by the store's store_currencies links). Use for formatting metadata (symbol, decimal digits).
  • Auth — anon: x-client-id required.
  • Request — query { code?, limit?, offset? } (code exact, lowercased; limit 1–200, default 50).
  • Response — ordered by code; a store with no enabled currencies returns an empty list.
{
  "currencies": [
    {
      "code": "eur",
      "name": "Euro",
      "symbol": "€",
      "symbol_native": "€",
      "decimal_digits": 2,
      "rounding": 0,
      "created_at": "2026-07-01T00:00:00.000Z",
      "updated_at": "2026-07-01T00:00:00.000Z"
    }
  ],
  "count": 1,
  "offset": 0,
  "limit": 50
}
  • Working curl
CURRENCIES=$(curl -sf "$BASE/api/store/currencies" -H "x-client-id: $CLIENT_ID")
echo "$CURRENCIES" | grep -q '"currencies"'
echo "$CURRENCIES" | grep -q '"code":"eur"'   # the dev store enables EUR
  • Errors — 400 missing_client_id, 400 validation_failed.
  • SDKlistCurrencies(client, query?).
  • Components — price formatting helpers.
  • Settings — Admin → Settings → Store → currencies (enable/disable + default).

GET /api/store/currencies/:code

  • Purpose — retrieve one currency by code (case-insensitive).
  • Auth — anon: x-client-id required.
  • RequestGET /api/store/currencies/{code} — no query.
  • Response{ "currency": { ...same shape as the list rows... } }
  • Working curl
CURRENCY=$(curl -sf "$BASE/api/store/currencies/eur" -H "x-client-id: $CLIENT_ID")
echo "$CURRENCY" | grep -q '"currency"'
echo "$CURRENCY" | grep -q '"symbol"'
  • Errors — 404 not_found.
  • CODE-TRUTH NOTE — unlike the list, the single read is NOT filtered by the store's enabled set: any currency in the shared catalog resolves. Treat the LIST as the authority on what the store supports.
  • SDKretrieveCurrency(client, code).
  • Components — price formatting helpers.
  • Settings — Admin → Settings → Store → currencies.

GET /api/store/locales

  • Purpose — the store's supported locale codes; drives the language switcher and the value your client sends as x-locale.
  • Auth — anon: x-client-id required.
  • Request — no query.
  • Response — default locale FIRST, then alphabetical:
{ "locales": ["en", "bg"] }
  • Working curl
LOCALES=$(curl -sf "$BASE/api/store/locales" -H "x-client-id: $CLIENT_ID")
echo "$LOCALES" | grep -q '"locales"'
echo "$LOCALES" | grep -q '"en"'
  • Errors — 400 missing_client_id.
  • SDKlistLocales(client).
  • Components — locale switcher; StorefrontClient's getLocale hook.
  • Settings — Admin → Settings → Store → locales (per-store store_locales manager; Cartbase's intentional divergence from Medusa's global locale catalog).