Taxonomy
FOLIO is organized into 24 top-level branches, each rooted at a specific OWL class and enumerated by the FOLIOTypes enum. The library exposes a get_<branch>() helper for every branch, plus the generic get_parents, get_children, and get_subgraph traversal methods for walking the class hierarchy by any IRI.
This page covers the 24 branch helpers, the depth controls that keep big branches fast, the dict-returning get_folio_branches() convenience, the three traversal primitives (and their gotchas), and the FOLIO_TYPE_IRIS map that lets you reference branch roots directly.
The 24 FOLIO branches
Every top-level branch is an entry in the FOLIOTypes enum, and every branch root’s short IRI lives in the FOLIO_TYPE_IRIS dictionary. Both are importable from folio.graph. The table below lists each branch, its helper method, its full-depth class count against the FOLIO 2.0.0 ontology, and a one-line description of what it covers.
| FOLIOTypes member | Helper method | Class count | What it covers |
|---|---|---|---|
ACTOR_PLAYER | get_player_actors() | 563 | Roles played by humans, organizations, or systems in legal matters |
AREA_OF_LAW | get_areas_of_law() | 174 | Substantive areas of legal practice |
ASSET_TYPE | get_asset_types() | 345 | Property and asset categories |
COMMUNICATION_MODALITY | get_communication_modalities() | 11 | Channels through which legal communication happens |
CURRENCY | get_currencies() | 178 | National and supranational currencies |
DATA_FORMAT | get_data_formats() | 17 | File and data formats (HTML, JSON, RTF, etc.) |
DOCUMENT_ARTIFACT | get_document_artifacts() | 2,796 | Document and artifact types |
ENGAGEMENT_TERMS | get_engagement_terms() | 343 | Terms governing legal engagements |
EVENT | get_events() | 401 | Legal events (meetings, depositions, hearings) |
FORUMS_VENUES | get_forum_venues() | 2,180 | Courts, tribunals, and other adjudicative venues |
GOVERNMENTAL_BODY | get_governmental_bodies() | 1,585 | Government agencies and bodies |
INDUSTRY | get_industries() | 2,137 | Industry categories |
LANGUAGE | get_languages() | 489 | Human languages |
FOLIO_TYPE | get_folio_types() | 3 | Meta-types (Instance, FOLIO Template, Query) |
LEGAL_AUTHORITIES | get_legal_authorities() | 82 | Sources of law (constitutions, statutes, regulations) |
LEGAL_ENTITY | get_legal_entities() | 517 | Legal-entity forms (corporations, partnerships, etc.) |
LOCATION | get_locations() | 3,782 | Geographic locations (countries, regions, cities) |
MATTER_NARRATIVE | get_matter_narratives() | 13 | Matter narrative types |
MATTER_NARRATIVE_FORMAT | get_matter_narrative_formats() | 2 | Narrative formats (HTML, TXT) |
OBJECTIVES | get_objectives() | 5,409 | Legal and business objectives |
SERVICE | get_services() | 434 | Legal services and practice areas |
STANDARDS_COMPATIBILITY | get_standards_compatibilities() | 868 | Standards and compliance frameworks |
STATUS | get_statuses() | 23 | Status values for engagements and services |
SYSTEM_IDENTIFIERS | get_system_identifiers() | 13 | System identifier types |
Two spelling notes worth burning in: the Actor / Player helper is get_player_actors() (not get_actors), and the Forums and Venues helper is get_forum_venues() (not get_forums_and_venues). Calling the wrong name raises AttributeError — the rest of the helpers match their branch names in the obvious way.
The counts above are at full depth — every descendant reachable from the branch root. If you want only the immediate children of a root (the top-level categories within a branch), pass max_depth=1. All 24 helpers share the same signature:
get_<branch>(max_depth: int = DEFAULT_MAX_DEPTH) -> List[OWLClass]where DEFAULT_MAX_DEPTH = 16 (imported from folio.graph). 16 is deep enough to reach every leaf in the current ontology without risking runaway recursion on a malformed import. You can always pass a smaller value for speed, or an explicit larger value if you ever graft a deeper taxonomy onto FOLIO.
Calling a branch helper
Each helper returns a flat list of OWLClass objects. Order is traversal order from the branch root, not sorted, so don’t rely on alphabetization.
Areas of Law
from folio import FOLIO
f = FOLIO()
areas = f.get_areas_of_law()
print(len(areas))
for c in areas[:3]:
print(repr(c.label))
# Output:
# 174
# 'Constitutional and Civil Rights Law'
# 'Individual Rights Law'
# 'Environmental, Social, and Governance Law'174 classes total — small enough to enumerate in full for most applications, including fanning out into an LLM prompt or populating a dropdown.
Locations
locations = f.get_locations()
print(len(locations))
for c in locations[:3]:
print(repr(c.label))
# Output:
# 3782
# 'Europe'
# 'Slovenia'
# 'Horjul'3,782 classes — the Location branch goes all the way down to municipalities, so the first few labels hitch a ride through Europe before the traversal unwinds. If you only need continents, countries, and U.S. states, use max_depth to cut the tree short.
Document types
docs = f.get_document_artifacts()
print(len(docs))
for c in docs[:3]:
print(repr(c.label))
# Output:
# 2796
# 'Document Provenance'
# 'Document Types'
# 'Legal Assistance Document'2,796 classes covering every document and artifact type FOLIO models — contracts, pleadings, opinions, forms, evidence exhibits, and so on.
Limiting depth with max_depth
Branch helpers fan out recursively to DEFAULT_MAX_DEPTH = 16. For a small branch like Areas of Law, that’s fine. For Locations, Industries, or Objectives — the multi-thousand-class branches — it can be noticeably slow if you only need the top-level categories.
Pass an explicit max_depth to stop early:
top_level = f.get_areas_of_law(max_depth=1)
print(len(top_level)) # only direct children of the Area of Law root
full_tree = f.get_areas_of_law()
print(len(full_tree))
# Output:
# 31
# 174Limit depth whenever you only need top-level categories, whenever you’re enumerating a branch just to show a hierarchy drill-down one level at a time, or whenever you’re pre-computing a facet dashboard over Locations / Industries / Objectives. For everything else, the full-depth default is fine — 16 covers every branch in the current ontology.
max_depth=0 is a special case: it short-circuits the recursion and returns an empty list (no descendants enumerated). That’s rarely what you want from a branch helper, but it’s handy as a sanity check. max_depth=1 is the most common manual value — it gives you exactly the direct children of the branch root.
All branches at once: get_folio_branches()
get_folio_branches() calls every branch helper for you and returns a Dict[FOLIOTypes, List[OWLClass]] keyed by the enum member — 24 keys, one per branch. (The docstring in the source still says List[OWLClass]; it’s a dict.) Useful for fanning out searches, building dashboards, or writing tooling that needs to reason over every branch at once.
branches = f.get_folio_branches(max_depth=1)
print(type(branches).__name__, len(branches))
for type_, classes in branches.items():
print(f"{type_.value}: {len(classes)}")
# Output:
# dict 24
# Actor / Player: 6
# Area of Law: 31
# Asset Type: 4
# Communication Modality: 3
# Currency: 178
# Data Format: 17
# Document / Artifact: 7
# Engagement Terms: 14
# Event: 14
# Forums and Venues: 3
# Governmental Body: 10
# Industry: 21
# Language: 487
# FOLIO Type: 3
# Legal Authorities: 14
# Legal Entity: 6
# Location: 8
# Matter Narrative: 8
# Matter Narrative Format: 2
# Objectives: 13
# Service: 5
# Standards Compatibility: 5
# Status: 3
# System Identifiers: 4Because the keys are FOLIOTypes enum members, type_.value gives you the human label ("Area of Law") and type_.name gives you the Python identifier ("AREA_OF_LAW").
A common idiom is to build a flat lookup from short IRI to branch label, so you can annotate search results with their branch of origin:
branches = f.get_folio_branches() # full depth
iri_to_branch = {
c.iri.rsplit("/", 1)[-1]: type_.value
for type_, classes in branches.items()
for c in classes
}
print(iri_to_branch["R8BD30978Ccbc4C2f0f8459f"])
# Output:
# LocationRun once at startup, reuse everywhere.
Traversing the taxonomy
The branch helpers are thin wrappers around three generic traversal methods. If you know a specific IRI and want to walk around it — for example, to render a breadcrumb trail, enumerate everything under a single area of law, or gather a self-contained subtree for an LLM prompt — call these directly.
get_parents(iri, max_depth=16)
Walks up the sub_class_of edges and returns the chain of ancestor classes. Two things to watch for:
- The list includes the starting class itself as element 0.
- The list ends with a synthetic
OWLClass(label=None, iri="http://www.w3.org/2002/07/owl#Thing")sentinel representing the OWL root. Any renderer that expectslabelto be a string must guard againstNone.
parents = f.get_parents("R8BD30978Ccbc4C2f0f8459f") # Michigan
print(len(parents))
for p in parents:
print(f"{p.label!r} -> {p.iri}")
# Output:
# 5
# 'Michigan' -> https://folio.openlegalstandard.org/R8BD30978Ccbc4C2f0f8459f
# 'United States of America (Location)' -> https://folio.openlegalstandard.org/R1E70ce4D699e90144cB32b8
# 'North America' -> https://folio.openlegalstandard.org/RE001ab376fa25C94f1244be
# 'Location' -> https://folio.openlegalstandard.org/R9aSzp9cEiBCzObnP92jYFX
# None -> http://www.w3.org/2002/07/owl#ThingFive elements: Michigan, its country, its continent, the Location branch root, and owl:Thing. If you want just the “real” ancestors, slice to parents[1:-1] or filter out label is None:
ancestors = [p for p in f.get_parents(iri) if p.label is not None and p.iri != iri]Because get_parents follows every sub_class_of edge, a class with multiple parents produces a wider-than-linear chain — the traversal recurses into each parent in turn, so you may see the same ancestor more than once when two branches converge higher up the tree.
get_children(iri, max_depth=16)
Walks down the parent_class_of edges and returns descendant classes. Unlike get_parents, it excludes the starting class. Unlike a proper set traversal, it can contain duplicates when the same class is reachable via multiple inheritance paths.
children = f.get_children("RCIPwpgRpMs1eVz4vPid0pV") # Contract Law
print(len(children))
for c in children:
print(repr(c.label))
# Output:
# 7
# 'Property Rights and Transactions Law'
# 'Civil Contract Law'
# 'Property Rights and Transactions Law'
# 'Commercial Transactions Law'
# 'Government Contracts Law'
# 'Employment Contracts Law'
# 'Independent Contractor Law'Note that Property Rights and Transactions Law appears twice — it’s a child of Contract Law through two different paths (a common pattern in FOLIO wherever one class legitimately falls under multiple parents). The duplicate is not a bug in the traversal; it’s a faithful enumeration of the graph. If you need unique results, dedupe by IRI:
seen = set()
unique = [c for c in children if not (c.iri in seen or seen.add(c.iri))]
print(len(unique)) # 6Calling get_children on a leaf class returns []:
print(f.get_children("R8BD30978Ccbc4C2f0f8459f")) # Michigan (leaf)
# Output:
# []get_subgraph(iri, max_depth=16)
Same as get_children, but includes the starting class as element 0. Use this when you want “everything under this branch including the root itself” — for example, when exporting a self-contained subtree to JSON or Markdown.
sub = f.get_subgraph("RCIPwpgRpMs1eVz4vPid0pV", max_depth=2) # Contract Law, 2 deep
print(len(sub))
for c in sub:
print(repr(c.label))
# Output:
# 8
# 'Contract Law'
# 'Property Rights and Transactions Law'
# 'Civil Contract Law'
# 'Property Rights and Transactions Law'
# 'Commercial Transactions Law'
# 'Government Contracts Law'
# 'Employment Contracts Law'
# 'Independent Contractor Law'Eight classes: Contract Law itself plus its seven descendants (including the same duplicate). Under the hood, every branch helper is self.get_children(FOLIO_TYPE_IRIS[<branch>], max_depth=...) — so whenever you need “the branch root plus everything below it,” reach for get_subgraph on the corresponding type IRI instead of the branch helper.
To summarize the three in one line: get_parents goes UP from an IRI (and includes self + an owl:Thing sentinel); get_children goes DOWN excluding self (may contain duplicates); get_subgraph goes DOWN including self (also may contain duplicates). All three accept a max_depth argument, all three return List[OWLClass], and all three accept short IRIs, full URIs, or legacy soli: / lmss.sali.org URLs interchangeably.
Branch IRI lookups
FOLIO_TYPE_IRIS is the canonical mapping from FOLIOTypes enum members to their root-class short IRIs. Import it directly when you need a branch root without calling a helper — for example, to pass as the parent_iri of a structured query.
from folio.graph import FOLIOTypes, FOLIO_TYPE_IRIS
area_of_law_iri = FOLIO_TYPE_IRIS[FOLIOTypes.AREA_OF_LAW]
print(area_of_law_iri)
# Use it as a query parent:
leaves = f.query(parent_iri=area_of_law_iri, has_children=False, limit=5)
for c in leaves:
print(repr(c.label))
# Output:
# RSYBzf149Mi5KE0YtmpUmr
# 'Patent Law'
# 'Reduction in Force Law'
# 'Trade Secret Law'
# 'Cybersecurity Law'
# "Indigenous People's Law"One thing to watch: the values in FOLIO_TYPE_IRIS are short IDs, not full URIs. If you need the full IRI form, prefix with https://folio.openlegalstandard.org/. All of the FOLIO client’s class-lookup and traversal methods accept either form — f[short_id], f[full_iri], and f.get_parents(short_id) all work — so you generally don’t need to expand the string yourself.
Reach for FOLIO_TYPE_IRIS directly (instead of calling a get_* helper) when you want the root class itself rather than its descendants — for example, to fetch metadata like the root’s definition, to use it as a parent_iri filter in query(), or to include it as the starting node in get_subgraph(). The branch helpers always start one level below the root, so they don’t return the root class.
See also
See also: Querying for filter-based access to taxonomy slices (including parent_iri and has_children), Properties & Relationships for object properties and the triples API, and API Reference for the complete method catalog.