Tax Jurisdictions
A Tax Jurisdiction is a place that levies tax — a country, a state or province, a city. It is the foundation of the whole tax engine, because every tax question starts with “where?”: where is the seller, where is the buyer, and therefore which taxes apply. Get the jurisdictions right and the rules above them practically write themselves.
The clever part — and the thing to understand before anything else — is that jurisdictions form a hierarchy. The United Kingdom contains England, Scotland, Wales, and Northern Ireland. Brazil contains São Paulo, Rio de Janeiro, and 25 other states. The engine uses that parent-child structure so a rule set once at country level automatically applies to every place inside it.
Access you'll need. Setting up and maintaining jurisdictions requires the Accounting Admin v2 or Accounting Controller v2 permission set. The Accounts Payable v2, Accounts Receivable v2, and Read Only v2 sets can view them but not change them.
The hierarchy — and ancestry matching
Each jurisdiction can point to a parent. Country records have no parent; a state points to its country; a city points to its state. That produces a tree:
├─ GB-ENG (England) → parent GB
├─ GB-SCT (Scotland) → parent GB
├─ GB-WLS (Wales) → parent GB
└─ GB-NIR (Northern Ireland) → parent GB
When the engine evaluates a transaction, it doesn’t just look at the exact
jurisdiction — it walks up the tree and collects the place
plus all its ancestors. A customer in England produces the set
{GB-ENG, GB}. A rule then matches if its jurisdiction is
anywhere in that set. So:
- A rule targeting
GBmatches the England customer (becauseGBis an ancestor). - A rule targeting
GB-ENGmatches too (exact hit). - A rule targeting
GB-SCTdoes not match (Scotland isn’t in the set).
This “ancestry matching” is why one country-level rule covers a whole nation, while you can still drop to a state-level rule when a single state differs (exactly how Brazil’s per-state ICMS rates work).
The fields — with UK & Brazil values
A jurisdiction is a small, deliberate record. Here is every field, what it does, and a real value from the shipped seed packs — a UK record (England) beside a Brazil record (São Paulo), both at State/Province level so you can compare like for like.
| Field | Type | Required | What it’s for | 🇬🇧 England | 🇧🇷 São Paulo |
|---|---|---|---|---|---|
| Jurisdiction Name | Text | Yes | Display name | England | São Paulo |
| Code | Text(20) · Unique · External ID | Yes | The engine’s match key — stable, human-readable | GB-ENG | BR-SP |
| Level | Picklist | Yes | Hierarchy tier — drives ancestry matching | State/Province | State/Province |
| Parent Jurisdiction | Lookup (self) | For non-country | The place above this one in the tree | GB | BR |
| Authority Type | Picklist | No | The body that administers the tax | State Tax Department | State Tax Department (SEFAZ-SP) |
| Country Code | Picklist (ISO 3166-1) | For country level | ISO country code | GB | BR |
| Currency Code | Picklist (ISO 4217) | No | Reference currency for seeding | GBP | BRL |
| Is Active | Checkbox (default true) | Yes | Unchecked → excluded from all matching | true | true |
| Notes | Long Text(500) | No | Free notes — treaties, thresholds, deadlines | — | “SP — largest economy. ICMS 18% standard.” |
The Code is the key — treat it with care
Of all these fields, Code is the one that matters most. It’s the engine’s matching key, the seed’s upsert key, and an External ID — which means it’s stable across org refreshes and package upgrades in a way Salesforce record IDs are not. The convention is strict and enforced:
| Level | Format | Examples |
|---|---|---|
| Country | ISO country code | GB, BR, US, IN |
| State / Province | Country‑State | GB-ENG, BR-SP, US-CA, IN-MH |
| City / Municipality | Country‑State‑City | BR-SP-SAO |
br-sp or
BR SP will be rejected on save.
How the engine uses jurisdictions
When an invoice posts, jurisdictions do four jobs. You don’t configure any of this — it’s the engine reading your records — but knowing it explains why your codes and parents have to be right.
1 · It walks the ancestry of both parties
The engine loads every jurisdiction once, then for the seller and the buyer it
builds the place-plus-ancestors set. Seller in São Paulo →
{BR-SP, BR} (the origin set). Buyer in Rio →
{BR-RJ, BR} (the destination set).
2 · It matches rules against those sets
A Tax Rule fires only if its origin and destination jurisdictions fall in the
matching sets (a blank on the rule means “any”). This is the ancestry
mechanism in action — a BR rule matches both SP and RJ; a
BR-RJ rule matches only Rio.
3 · It derives the fiscal operation from the codes
The engine compares the two codes to classify the transaction — entirely from the text:
| Comparison | Result | Example |
|---|---|---|
| Same country, same state | Intrastate | BR-SP → BR-SP |
| Same country, different state | Interstate | BR-SP → BR-RJ |
| Different country | Export | GB → FR |
That derived operation feeds straight into Fiscal Operations and decides, for Brazil, whether you’re on the interstate rule set (and thus whether DIFAL applies).
4 · It gates nexus
Before any tax is charged, the engine checks whether your entity is
registered to collect tax in the buyer’s jurisdiction —
and it accepts a registration at any ancestor. A single US-TX
registration covers a buyer in a Texas city; a GB registration covers
all four UK nations. (See Entity Tax
Registration.)
Real data: UK and Brazil jurisdictions
Here is what the seed packs actually create.
🇬🇧 United Kingdom — 5 records
| Code | Name | Level | Parent | Currency |
|---|---|---|---|---|
GB | United Kingdom | Country | — | GBP |
GB-ENG | England | State/Province | GB | GBP |
GB-SCT | Scotland | State/Province | GB | GBP |
GB-WLS | Wales | State/Province | GB | GBP |
GB-NIR | Northern Ireland | State/Province | GB | GBP |
VAT is UK-wide, so the four nations exist mainly for completeness and the few cases
that differ (Northern Ireland follows EU VAT rules for goods under the Windsor
Framework). The VAT rules all sit at GB level.
🇧🇷 Brazil — 28 records (a sample)
| Code | Name | Level | Parent | Note (from seed) |
|---|---|---|---|---|
BR | Brazil | Country | — | Receita Federal (RFB) |
BR-SP | São Paulo | State/Province | BR | ICMS 18% standard |
BR-RJ | Rio de Janeiro | State/Province | BR | ICMS 20%; FCP 2% applies |
| … plus MG, RS, BA and the other 22 states | ||||
Brazil needs every state because ICMS rates and surcharges genuinely differ by
state — SP at 18%, RJ at 20% with a 2% poverty-fund surcharge. The hierarchy
lets each state carry its own rules while shared federal taxes (IPI, PIS, COFINS)
sit at BR level.
Worked example: why São Paulo → Rio is “interstate”
A São Paulo seller invoices a Rio de Janeiro customer. Watch the jurisdictions do their work:
{BR-SP, BR}; Destination (buyer) = {BR-RJ, BR}.BR (same country) but the state segments differ — SP vs RJ — so the engine classifies the sale as Interstate.BR-RJ) and Rio FCP rule (2%, destination BR-RJ) fire too, all because BR-RJ is in the destination set. The federal rules (IPI, PIS, COFINS) match with no jurisdiction restriction at all.That single change — the buyer’s jurisdiction — reshapes the whole tax outcome. It’s why getting the Tax Jurisdiction on each customer Account right is so important.
Built-in guardrails
Four validation rules keep jurisdiction data clean — because the engine depends on it:
| Rule | What it blocks |
|---|---|
| Code must be uppercase | br-sp — the code derivation is case-sensitive |
| Code cannot contain spaces | BR SP — use a hyphen |
| Parent required for non-country | A state/city with no parent — it would float free of the hierarchy |
| Cannot be its own parent | A record pointing to itself — would loop the ancestry walk |
Setting up & maintaining
- You usually don’t create these by hand. The Tax Seeding Wizard creates a country’s full jurisdiction set — countries first, then their children — in the right order so parents always exist before the records that point to them.
- Deactivate, don’t delete. Unchecking Is Active removes a jurisdiction from matching while preserving history on past invoices. Deleting one that historical records rely on would orphan them.
- Add a tier only when a tax needs it. The seed uses Country and State/Province levels; Municipality, District, and Region exist for city taxes (Brazil’s ISS, US special districts) — add them when a rule actually targets that level.
Where to go next
- Tax Types — the taxes a jurisdiction levies.
- Tax Rules — rules scoped to a jurisdiction.
- Entity Tax Registration — registering to collect in a jurisdiction.
- Tax Seeding Wizard — load jurisdictions automatically.
Frequently asked questions
Only the ones your rules need. For the UK, the country record alone carries the VAT rules — the four nations are optional. For Brazil, you need each state whose ICMS rate or surcharge differs (which, in practice, is most of them). The seed gives you the full set so you don’t have to decide up front.
Because the code is doing real work: it’s the engine’s match key, the seed’s upsert key, and the basis for deriving intrastate/interstate/export. A stable text code survives org refreshes and upgrades; a record ID does not. That’s why the format is enforced.
The Tax Jurisdiction field on the customer’s Account (and on your Entity for the seller side). The engine reads those two to get origin and destination. Covered in Party Tax Profiles.
Yes — that’s the whole point of the hierarchy. Keep the shared rule at country level, and add a more specific rule at the state level for the exception. Both can match; the engine applies the rules that fit (tax rules don’t “stop at the first match”). How to scope that precisely is covered in Tax Rules.
Was this article helpful?