Multi-Region Commerce
Configure regions, currencies, taxes, and localized pricing
This guide covers setting up multi-region selling in Hanzo Commerce, including region configuration, currency handling, per-region tax rules, and localized product pricing.
Overview
Regions control how your store operates in different markets:
Region → Currency, Tax Rules, Payment Providers, Fulfillment Options
→ Countries (exclusive: one country per region)
→ Localized PricingStep 1: Create Regions
Define a region for each market you sell into:
curl -X POST https://api.hanzo.ai/region \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "North America",
"currency": "USD",
"taxIncluded": false,
"countries": [
{"code": "US"},
{"code": "CA"}
],
"paymentProviders": ["stripe"],
"fulfillmentProviders": ["manual"]
}'const northAmerica = await commerce.regions.create({
name: 'North America',
currency: 'USD',
taxIncluded: false,
countries: [{ code: 'US' }, { code: 'CA' }],
paymentProviders: ['stripe'],
fulfillmentProviders: ['manual']
})
const europe = await commerce.regions.create({
name: 'Europe',
currency: 'EUR',
taxIncluded: true,
countries: [{ code: 'DE' }, { code: 'FR' }, { code: 'IT' }, { code: 'ES' }],
paymentProviders: ['stripe'],
fulfillmentProviders: ['manual', 'dhl']
})Each country can only belong to one region. The taxIncluded flag determines whether prices displayed to customers include tax (common in Europe) or exclude tax (common in the US).
Step 2: Currency Handling
Each region has a single currency. Prices are stored in the smallest currency unit (cents):
| Region | Currency | $29.99 stored as |
|---|---|---|
| North America | USD | 2999 |
| Europe | EUR | 2999 |
| Japan | JPY | 2999 (no decimals) |
| UK | GBP | 2999 |
When querying products, pass the region to get localized prices:
curl "https://api.hanzo.ai/product?regionId=reg_europe" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"Step 3: Localized Pricing
Set different prices per region for the same product:
curl -X POST https://api.hanzo.ai/product/prod_abc123/price \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"prices": [
{
"regionId": "reg_north_america",
"amount": 2999,
"currency": "USD"
},
{
"regionId": "reg_europe",
"amount": 2799,
"currency": "EUR"
},
{
"regionId": "reg_japan",
"amount": 4500,
"currency": "JPY"
}
]
}'await commerce.products.setPrices('prod_abc123', {
prices: [
{ regionId: northAmerica.id, amount: 2999, currency: 'USD' },
{ regionId: europe.id, amount: 2799, currency: 'EUR' },
{ regionId: japan.id, amount: 4500, currency: 'JPY' }
]
})Step 4: Tax Configuration Per Region
US: Tax-Exclusive Pricing
For the US, taxes are calculated at checkout and added to the displayed price:
curl -X POST https://api.hanzo.ai/taxregion \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "United States",
"countryCode": "US",
"defaultTaxRate": 0,
"providerId": "txprov_auto"
}'The automatic tax provider calculates state, county, and city taxes based on the shipping address.
EU: Tax-Inclusive Pricing (VAT)
For Europe, prices include VAT. Create tax rates for each country:
curl -X POST https://api.hanzo.ai/taxrate \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"taxRegionId": "txreg_eu",
"name": "Germany VAT",
"rate": 0.19,
"code": "DE-VAT"
}'curl -X POST https://api.hanzo.ai/taxraterule \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"taxRateId": "txrate_de_vat",
"type": "province",
"reference": "DE"
}'Common EU VAT Rates
| Country | Standard Rate |
|---|---|
| Germany | 19% |
| France | 20% |
| Italy | 22% |
| Spain | 21% |
| Netherlands | 21% |
Step 5: Link Fulfillment to Regions
Associate stock locations with regions for fulfillment routing:
curl -X POST https://api.hanzo.ai/region/reg_europe/stocklocation \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"stockLocationIds": ["sloc_berlin"]
}'This ensures European orders are routed to the Berlin warehouse.
Detecting Customer Region
Automatically detect a customer's region from their IP or shipping address:
curl "https://api.hanzo.ai/region/detect?country=DE" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"Response:
{
"id": "reg_europe",
"name": "Europe",
"currency": "EUR",
"taxIncluded": true
}In your storefront, detect on page load:
const region = await commerce.regions.detect({ country: customerCountry })
// Use region for all subsequent product and cart calls
const products = await commerce.products.list({ regionId: region.id })
const cart = await commerce.carts.create({ regionId: region.id })Managing Countries
Add or remove countries from a region as your business expands:
# Add countries
curl -X POST https://api.hanzo.ai/region/reg_europe/countries \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"countries": [{"code": "PL"}, {"code": "CZ"}]
}'
# Remove a country
curl -X DELETE https://api.hanzo.ai/region/reg_europe/countries/CZ \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"await commerce.regions.addCountries(europe.id, {
countries: [{ code: 'PL' }, { code: 'CZ' }]
})
await commerce.regions.removeCountry(europe.id, 'CZ')Removing a country from a region makes your store unavailable in that market. Existing orders from that country are not affected, but new orders cannot be placed.
How is this guide?
Last updated on