“Give me all NDAs, signed, valid in France, where the counterparty is Acme.”That query doesn’t rely on finding those exact words in the document body. It relies on structured metadata you’ve attached to the file: a type (
nda), a flag (signed = true), a jurisdiction, a counterparty name. This works for any document type: contracts, invoices, HR policies, technical specs, whatever your app needs.
Workspaces, tags, or facets?
Facets aren’t the only way to organise documents. Workspaces are containers that isolate a team’s or customer’s files, and tags are flat labels that group files into collections (even across workspaces) with zero schema to design. The three compose: a file lives in one workspace, can carry several tags, and can be classified with facets.
Only workspaces are a permission boundary: API keys can be scoped to specific workspaces, so segment data that needs different permission levels with workspaces rather than facets. Reach for the simplest layer that solves your problem. The rest of this tutorial covers facets.
How it works
Facets are built on three layers:- Build your classification trees: create content types and their attributes (
POST /api/v3/content-types), or adopt a ready-made starter kit (legal, finance, healthcare, tech, manufacturing) viaGET /api/v3/content-types/templates - Classify files & set values: assign a content type to each file and fill in its attribute values (
POST /api/v3/files/{id}/facets) - Query by metadata: filter files by content type and attribute values (
GET /api/v3/files)
Glossary
Content Type
A Content Type is a node in your company’s classification tree: a named, hierarchical label that describes what a document is. Content types live in a tree up to 4 levels deep. The path between levels uses: as separator.
Each Content Type has:
code: a short kebab-case identifier, unique among siblings (nda,service-agreement)label: the human-readable name ("Non-Disclosure Agreement")description: explains what this type means, used by AI to classify documents automaticallyinherit_attributes: whether documents classified here also get the parent node’s attributes
Attribute
An Attribute is a custom attribute attached to a Content Type. It describes what data a document of that type should carry.
Available attribute types:
Classification
A Classification is the link between a specific file and a Content Type path. It answers the question: “What type is this document?” One file can have multiple classifications. A single document might be both acontract:nda and a contract:data-processing-agreement at the same time.
Attribute Value
An Attribute Value is the actual data stored for a specific attribute on a specific classification of a specific file. When a file is classified ascontract:nda and you set counterparty = "Acme Corp", you’ve created an Attribute Value: {file: #1234, path: "contract:nda", name: "counterparty", value: "Acme Corp"}.
Values are scoped by content type path. If a file has two classifications, each classification has its own set of values. They don’t mix.
Inherited Attributes
When a Content Type node hasinherit_attributes: true, files classified at any descendant node automatically have access to the attributes defined on that ancestor.
contract:nda also defines its own attribute is_mutual (boolean), then a file classified as contract:nda sees all three fields: counterparty and jurisdiction (inherited from contract) plus is_mutual (defined directly on contract:nda).
Why it matters
Facets also enrich the BM25 lexical search index automatically. When you set attribute values on a file, LightOn reindexes that file’s text to include the content type labels and attribute values. Semantic search queries benefit from this enrichment without any extra work on your side.
Limits at a glance
For the full list, see the Rules & constraints reference.
Next steps
Building a classification tree
Create content types and custom attributes
Classifying files & setting metadata
Classify files and set attribute values
Filtering documents by metadata
Query by content type and attribute value