Organizing labels
Create labels in your organization’s catalog:- Python
- TypeScript
- cURL
^[a-z0-9]+(?:_[a-z0-9]+)*$ (underscores, no hyphens — audit_only).
The PATCH endpoint updates only description. Labels in the catalog are
reusable: multiple workspaces can include the same label.
Workspace-level labels
When you create a workspace, you freeze a subset of your organization’s label catalog as the workspace’s allowed set:- Python
- TypeScript
- cURL
{name, description} — description is the classifier
prompt. Create matching catalog entries when you want a shared vocabulary;
create does not require the name to already exist in the catalog. A file’s
labels must be a subset of this allowed set. The set is immutable: changing
it requires a new workspace.
default_label is applied to files uploaded without an explicit label.
File-level labels
Uploadmetadata.labels is caller-supplied key-value metadata
({"year":"2025"}), not the access catalog. Visibility labels are assigned
at ingestion from the workspace’s frozen set (see below). A file’s labels
must be a subset of that allowed set.
Coverage reporting
Every tool and query response includescoverage — how many candidates were
withheld by the access predicate and which labels would unlock them:
restricted_candidates— Files visible in scope but withheld by your key’s access predicate.labels_required— Labels your key would need to see the withheld files.
Your key’s scope
An API key’s access predicate is set when the key is created. When you call a tool in a workspace, the API filters results to files visible to your key and returnscoverage describing what was withheld.
A file carries one visibility label and is visible when that label is in the
key’s granted set (or when the file has no label). Reading a source whose
documents carry several distinct labels requires the key to hold all of them.
Label catalog management
- Python
- TypeScript
- cURL
Automatic classification at ingestion
When a workspace declares labels, NDI automatically classifies each logical document produced during ingestion using the label descriptions as prompts. How it works:- After a document file is parsed and split into logical documents, a classification step reads each document’s markdown content.
- An LLM call compares the content against your label descriptions and assigns
the best matching label — or marks the document as intentionally unlabelled
(
nulllabel, visible to everyone) when no label fits. - If classification fails for any reason, the document falls back to
default_labelso ingestion always completes.