23 "note": "A wc/v3/taxes row's `country` + `state` columns map to one Tax Region (country + optional ISO 3166-2 subdivision, without the country prefix). `postcode`/`postcodes` and `city`/`cities` have NO Wix Tax Region equivalent -- Wix's region model stops at country/subdivision (see pitfalls). `priority`/`compound`/`order` (rate stacking/ordering) also have no direct Tax Region/Manual Tax Mapping field; a compound-rate WooCommerce setup needs the 'tax breakdowns' multi-mapping pattern documented in manual-tax-mapping.json, not a Tax Region field."
24 }
25 ],
26 "preferredWrite": {
27 "surface": "Tax Regions",
28 "endpoint": "POST /billing/v1/tax-regions",
29 "writerId": "createTaxRegion",
30 "verification": "verified-live",
31 "importSafe": true,
32 "bulk": false
33 },
34 "fallbacks": [
35 {
36 "classification": "skip-by-default",
37 "when": "No source has any wc/v3/taxes rows (an anonymized verification environment's actual state, verified live 2026-08-12: 0 rows) -- there is nothing to create a region FOR. Do not pre-create speculative regions; wait for real rate data."
38 },
39 {
40 "classification": "cms",
41 "when": "A source rate row is scoped narrower than subdivision (postcode or city) -- Wix Tax Region has no field for either. Record the narrower scope as a mapping gap rather than silently widening it to the whole subdivision/country, which would change who gets charged tax."
42 }
43 ],
44 "reliability": {
45 "status": "reliable",
46 "flags": []
47 },
48 "pitfalls": [
49 {
50 "code": "tax-apis-live-under-billing-v1",
51 "severity": "warning",
52 "summary": "Create/Query/Delete Tax Region are `/billing/v1/tax-regions...`, not `/ecom/v1/...`."
53 },
54 {
55 "code": "never-hardcode-the-calculator-appid",
56 "severity": "blocker",
57 "summary": "appId is required and installation-scoped. Resolve it with List Tax Calculators immediately before creating a region. A source manual rate must select the non-Avalara calculator by display name through resolveManualTaxCalculatorAppId in wix-writers.js, never a hardcoded installation-specific ID."
58 },
59 {
60 "code": "no-postcode-or-city-granularity",
61 "severity": "blocker",
62 "summary": "The TaxRegion object has exactly two location fields: `country` (ISO 3166-1 alpha-2) and `subdivision` (ISO 3166-2 without country prefix). There is no postcode/zip or city field. A WooCommerce tax rate scoped to `postcode`/`postcodes` or `city`/`cities` cannot be represented at that granularity -- it must be flattened to the containing subdivision (or country, if the source didn't even specify one), which is a real, not cosmetic, change to who is charged. Record this as an explicit mapping gap per affected source row rather than silently widening scope."
63 },
64 {
65 "code": "subdivisions-only-for-14-countries",
66 "severity": "warning",
67 "summary": "Subdivision-level regions are accepted only for AU, BR, CA, FR, DE, IN, IT, MX, NL, PT, ES, AE, GB, US. For any other country, create the region at country level (omit `subdivision` or pass `*`); passing one anyway risks `SUBDIVISIONS_NOT_SUPPORTED_FOR_COUNTRY`."
68 },
69 {
70 "code": "iso-codes-not-display-names",
71 "severity": "blocker",
72 "summary": "`country`/`subdivision` are stored as ISO codes ONLY -- no display name is kept anywhere, so there is no way to recover 'New York' from a stored `NY` later, and storing 'New York' instead of `NY` doesn't error, it just silently matches nothing at Calculate Tax time. WooCommerce's `state` column is typically already an ISO-ish code (e.g. `US-NY` region format varies by version) -- verify the exact source format per site before stripping/mapping it, don't assume it is already bare ISO 3166-2."
77 "summary": "Create Tax Region 409s `ALREADY_EXISTS` for a second region with the same (country, subdivision) pair -- dedupe by that pair before creating, the same way product/category dedupe works elsewhere in this pipeline, rather than relying on the API's rejection as the dedupe mechanism."
78 },
79 {
80 "code": "embargoed-countries-rejected",
81 "severity": "info",
82 "summary": "Tax regions can't be created for Cuba, Iran, North Korea, or Syria."
83 }
84 ],
85 "mappingGuidance": [
86 "Group WooCommerce wc/v3/taxes rows by (country, state) before creating regions -- one Wix Tax Region per distinct pair, not per source row (a source site can have multiple rows -- e.g. standard/reduced/zero rate -- sharing the same region, which fan out to separate Manual Tax Mappings against ONE region).",
87 "Resolve the manual calculator's appId once per import run (it doesn't change mid-run) and reuse it for every region create in that run.",
88 "When a source rate has no state/province value, create a country-level region (omit subdivision) rather than guessing a default subdivision."