Skip to main content
This tutorial uses GET /api/v3/files. The full schema for every filter parameter lives in the API reference.
Your files are classified and enriched with metadata. Now your app needs to query them: not by what the text says, but by what they are and what their metadata contains. Imagine you’ve uploaded 200 contracts and classified them with facets. Your app needs to answer: “Show all unsigned French NDAs with Acme.” Here’s how to build that query, step by step.

Filter by content type

The content_type parameter filters files by their classification path.

Exact match + subtree

A plain path matches the exact node and all its descendants:

OR across types

Comma-separate multiple paths for an OR query:

Wildcard: contains

Wrap in * to match any path containing the substring:

Wildcard: prefix

Append * for a prefix match:

Filter by attribute value

The attribute parameter filters by attribute name and optionally by value and operator.

Has any value

Exact match

OR across values

Use | (pipe) as the OR delimiter. It’s the recommended separator and avoids ambiguity with commas in multi-key values:

Comparison operators

Use >, <, >=, <= for numbers and dates:

Prefix match

Boolean

Date shortcuts

LightOn expands partial dates into ranges automatically:
For details on date ambiguity, multi-select containment, and which types are filterable, see Rules & constraints.

Combining filters (AND logic)

When you repeat attribute=, each additional filter narrows the results (AND logic). For example, to find files where jurisdiction is FR and signed is true:

Scoping an attribute to a specific content type

When a file has multiple classifications, the same attribute name may exist under different paths. Use the explicit scope syntax to be precise. When you include a content_type filter alongside attribute filters, attributes are automatically scoped to that content type. You don’t need the explicit scope syntax unless you’re filtering across multiple content types:

Putting it all together

Here’s the full query from our scenario: all signed French NDAs.
The response is a paginated list of file objects. If no files match, you get an empty results array with a 200 status code.

Full operator reference

Repeated ?attribute= → AND. Use | (pipe) for OR within a value. Comma-separated ?content_type=a,b → OR across content types. content_type and attribute are supported directly in the request body of both POST /api/v3/search and POST /api/v3/ask. No need to pre-filter files: just add facet fields to your query and LightOn narrows the corpus for you.

Search by content type

Scope a search to a specific document type. LightOn returns ranked chunks from matching files only.
search_by_content_type.py

Search by attributes

Scope a search by attribute values, without specifying a content type.
search_by_attributes.py

Search by content type and attributes

Combine both for precise scoping: only unsigned French NDAs.
search_by_content_type_and_attributes.py

Ask: get an LLM answer from facet-filtered documents

POST /api/v3/ask works the same way. LightOn retrieves relevant passages from matching documents, then generates a grounded answer.
ask_by_content_type_and_attributes.py

BM25 enrichment

Facets also improve search quality automatically. When you set attribute values, LightOn appends the content type labels and attribute values to the file’s BM25 lexical index. A query like “unsigned NDAs with Acme” benefits from the enriched index even if the document body doesn’t mention “unsigned” or “Acme” explicitly. This reindexing happens after every write.