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-idrequired. - Request —
GET /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
countriesarray (divergence from Medusa's Store API — country/tax scope lives server-side intax_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), 400validation_failed(bad limit/offset). - SDK —
listRegions(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-idrequired. - Request —
GET /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"'- SDK —
retrieveRegion(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_currencieslinks). Use for formatting metadata (symbol, decimal digits). - Auth — anon:
x-client-idrequired. - Request — query
{ code?, limit?, offset? }(codeexact, lowercased;limit1–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, 400validation_failed. - SDK —
listCurrencies(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-idrequired. - Request —
GET /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.
- SDK —
retrieveCurrency(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-idrequired. - 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. - SDK —
listLocales(client). - Components — locale switcher;
StorefrontClient'sgetLocalehook. - Settings — Admin → Settings → Store → locales (per-store
store_localesmanager; Cartbase's intentional divergence from Medusa's global locale catalog).