This document provides a practical overview of the current AI-Ready-Ingest backend API.
It is intended for developers and downstream consumers who need to:
- discover backend capabilities
- inspect canonical corpus resources
- manage curated collections
- access grounded text spans
- retrieve derived enrichments
- perform search over extracted content
- run ingestion and embedding workflows
This overview is descriptive and implementation-aligned. Exact request and response schemas should be defined in openapi.yaml.
The backend API is resource-oriented and centered on core backend capabilities.
User-facing dashboard rendering does not live in this repository.
Downstream consumers should use:
- scope resources
- collection resources
- object resources
- text-span resources
- enrichment resources
- search resources
Compatibility read routes under /api/osii/... still exist, but new integrations should prefer the newer resource-oriented route families.
By default the application commonly runs on:
http://localhost:8511
The OSII store is typically located at:
.\osii-data\.osii
The shared data root is typically:
.\osii-data\source
Canonical collection metadata is stored inside the OSII store, typically at:
.\osii-data\.osii\collections\<collection-id>\collection.toml
The disposable .osii\state\catalog.sqlite3 database accelerates API reads and
can always be rebuilt from canonical files.
Collection metadata must survive:
- extraction reruns
- synthesis reruns
- embedding rebuilds
Collection membership must reference stable object identifiers such as file_id, not only transient filesystem paths.
GET /api/scopes/rootGET /api/scopes/foldersGET /api/scopes/collectionsPOST /api/scopes/describe
GET /api/collectionsPOST /api/collectionsGET /api/collections/{collection_id}PATCH /api/collections/{collection_id}DELETE /api/collections/{collection_id}GET /api/collections/{collection_id}/membersPOST /api/collections/{collection_id}/membersDELETE /api/collections/{collection_id}/members/{file_id}GET /api/collections/{collection_id}/exportPOST /api/packages/import
GET /api/objects/{file_id}GET /api/objects/{file_id}/manifestGET /api/objects/{file_id}/textsGET /api/objects/{file_id}/texts/preferredGET /api/objects/{file_id}/synthesesGET /api/objects/{file_id}/governancePUT /api/objects/{file_id}/governancePOST /api/objects/{file_id}/deletion-previewDELETE /api/objects/{file_id}
GET /api/text/objects/{file_id}/spanGET /api/text/objects/{file_id}/span/context
POST /api/enrichments/listGET /api/enrichments/objects/{file_id}/{filename}
GET /api/search
GET /api/intake/readinessGET /api/browsePOST /api/resolveGET /api/extractorsGET /api/synthesizersGET /api/folder-synthesizersPOST /api/runsGET /api/runs/{run_id}GET /api/runs/{run_id}/logsPOST /api/embeddings/buildGET /api/embeddings/build/{job_id}GET /api/embeddings/meta
GET /api/admin/setupreturns the human-facing readiness summary, selected methods, provider presence, and capability-service state.PUT /api/admin/model-providers/{provider_id}/credentialaccepts an API key as a write-only value when local.envwrites are enabled.DELETE /api/admin/model-providers/{provider_id}/credentialforgets a key previously saved by OSII.GET /api/admin/serviceslists allowlisted capability services.POST /api/admin/services/{service_id}/{start|stop|restart}controls only a service owned by the local launcher.GET /api/admin/services/{service_id}/logsreturns a bounded recent log tail.
Credential responses report presence and source but never return the value.
The service-control endpoints return 503 in deployments without the local
loopback supervisor.
- compatibility read routes under
/api/osii/... GET /artifact/{file_path:path}
The API prefers stable identifiers in canonical read paths:
file_idfolder_idcollection_idrun_idjob_id
Where relevant, source-relative paths are exposed as canonical relpaths rooted at the shared data root, for example:
reports/FY26/Q2_Status_Report.pdf
Downstream consumers should distinguish between:
- canonical stored artifacts, such as object text and manifest spans
- derived artifacts, such as enrichments and syntheses
- retrieval/index artifacts, such as embedding chunks and FAISS identifiers
The resource model and search semantics documents define these distinctions more precisely.
Scope resources provide a uniform way to describe root, folder, collection, and object scopes.
GET /api/scopes/rootExample response:
{
"scope": {
"scope_type": "root",
"scope_id": "root",
"label": "root"
},
"member_file_ids": [
"sha256-test123"
]
}GET /api/scopes/foldersThis returns a flat catalog of folder scope descriptors.
Example response:
{
"scopes": [
{
"scope_type": "folder",
"scope_id": "folder-root",
"folder_id": "folder-root",
"path": "",
"label": "root-folder"
}
]
}GET /api/scopes/collectionsThis returns collection scope descriptors, not full collection resources.
Example response:
{
"scopes": [
{
"scope_type": "collection",
"scope_id": "col-abc123def456",
"collection_id": "col-abc123def456",
"label": "sensor-calibration-review",
"kind": "file-list",
"description": "Documents related to calibration methods and drift analysis.",
"document_count": 2
}
]
}POST /api/scopes/describe
Content-Type: application/jsonSupported request variants:
- root
- folder by
folder_id - collection by
collection_id - object by
file_id
Example request:
{
"scope_type": "collection",
"collection_id": "col-abc123def456"
}Example response:
{
"scope": {
"scope_type": "collection",
"scope_id": "col-abc123def456",
"collection_id": "col-abc123def456",
"label": "sensor-calibration-review"
},
"member_file_ids": [
"sha256-test123"
]
}Folder scope behavior is subtree-based for filtering and search semantics.
Collections are curated groupings of documents. They are not canonical OSII hierarchy nodes.
GET /api/collectionsExample response:
{
"collections": [
{
"id": "col-abc123def456",
"name": "sensor-calibration-review",
"description": "Documents related to calibration methods and drift analysis.",
"kind": "file-list",
"color": "#3366ff",
"document_count": 2,
"created_utc": "2026-06-18T12:00:00Z",
"updated_utc": "2026-06-18T12:05:00Z"
}
]
}POST /api/collections
Content-Type: application/jsonRequired fields:
name
Optional fields:
descriptionkindcolor
Example request:
{
"name": "sensor-calibration-review",
"description": "Documents related to calibration methods and drift analysis.",
"kind": "file-list",
"color": "#3366ff"
}Example response:
{
"collection": {
"id": "col-abc123def456",
"name": "sensor-calibration-review",
"description": "Documents related to calibration methods and drift analysis.",
"kind": "file-list",
"color": "#3366ff",
"document_count": 0,
"created_utc": "2026-06-18T12:00:00Z",
"updated_utc": "2026-06-18T12:00:00Z"
}
}PATCH /api/collections/{collection_id}
Content-Type: application/jsonWritable fields:
namedescriptionkindcolor
Example request:
{
"description": "Updated description",
"kind": "manual"
}GET /api/collections/{collection_id}DELETE /api/collections/{collection_id}GET /api/collections/{collection_id}/membersExample response:
{
"collection": {
"id": "col-abc123def456",
"name": "sensor-calibration-review",
"description": "Documents related to calibration methods and drift analysis.",
"kind": "file-list",
"color": "#3366ff",
"document_count": 2,
"created_utc": "2026-06-18T12:00:00Z",
"updated_utc": "2026-06-18T12:05:00Z"
},
"file_ids": [
"sha256-test123"
]
}POST /api/collections/{collection_id}/members
Content-Type: application/jsonMembership addition is batch-oriented and effectively idempotent.
DELETE /api/collections/{collection_id}/members/{file_id}Removal is success/no-op style. If the collection exists but the document is not currently a member, the response reports removed: false rather than treating that case as an error.
GET /api/collections/{collection_id}/export
POST /api/packages/importExport returns a ZIP containing collection and object sidecars plus a versioned
osii-package.json checksum manifest; it never includes source files. Import
uses multipart field package, validates every member before writing, merges
objects by immutable file_id, unions governance labels, and invalidates
corpus-wide derived indexes. See sensitive data and transfer.
Object resources provide the preferred read surface for canonical object metadata, text access, syntheses, and related summaries.
GET /api/objects/{file_id}/governance
PUT /api/objects/{file_id}/governanceThe JSON fields are sensitivity_labels, tags, and handling_notes. They are
stored canonically in objects/<file_id>/governance.toml and communicate
awareness; they do not enforce access control.
POST /api/objects/{file_id}/deletion-preview
DELETE /api/objects/{file_id}Preview accepts mode sidecar_only or source_and_sidecar. Delete requires the
same mode, the returned preview_token, and confirmation exactly equal to the
file ID. Active Intake jobs or a stale preview block deletion.
GET /api/objects/{file_id}Example response:
{
"file_id": "sha256-test123",
"meta": {
"file": {
"source_relpath": "reports/example.pdf",
"filename": "example.pdf",
"mime": "application/pdf",
"size_bytes": 1234,
"mtime_utc": "2026-05-21T00:00:00Z"
},
"hash": {
"sha256": "test123"
}
},
"overview": {
"file_id": "sha256-test123",
"meta": {
"file": {
"source_relpath": "reports/example.pdf",
"filename": "example.pdf",
"mime": "application/pdf",
"size_bytes": 1234,
"mtime_utc": "2026-05-21T00:00:00Z"
},
"hash": {
"sha256": "test123"
}
},
"text_count": 1,
"image_count": 0,
"has_synth": true,
"text_items": [
{
"kind": "text",
"id": "seg-000001",
"path": "text.txt",
"type": "page",
"span": {
"char_start": 0,
"char_end": 38
},
"source_origin": {
"source_type": "pdf",
"unit_type": "page",
"page": 1
},
"related_ids": []
}
],
"image_items": []
},
"collections": [
{
"id": "col-abc123def456",
"name": "sensor-calibration-review",
"kind": "file-list"
}
],
"processing": {
"extractor": {
"name": null,
"display_name": null
},
"synthesizer": {
"name": null,
"display_name": null
},
"canonical_text_path": "objects/sha256-test123/text.txt",
"editable_text_path": null,
"has_editable_text": false,
"capabilities": {
"supports_markdown_render": false
}
},
"enrichments": [
{
"name": "keywords--stats_keywords.json",
"kind": "file",
"relpath": "objects/sha256-test123/enrichments/keywords--stats_keywords.json"
}
]
}GET /api/objects/{file_id}/manifestExample response:
{
"file_id": "sha256-test123",
"records": [
{
"kind": "text",
"id": "seg-000001",
"path": "text.txt",
"type": "page",
"span": {
"char_start": 0,
"char_end": 38
},
"source_origin": {
"source_type": "pdf",
"unit_type": "page",
"page": 1
},
"related_ids": []
}
]
}GET /api/objects/{file_id}/textsExample response:
{
"file_id": "sha256-test123",
"representations": [
{
"name": "canonical",
"kind": "canonical_extracted_text",
"path": "objects/sha256-test123/text.txt",
"exists": true,
"preferred": true
},
{
"name": "editable",
"kind": "editable_text",
"path": "objects/sha256-test123/editable_text.txt",
"exists": false,
"preferred": false
}
],
"segments": [
{
"kind": "text",
"id": "seg-000001",
"path": "text.txt",
"type": "page",
"span": {
"char_start": 0,
"char_end": 38
},
"source_origin": {
"source_type": "pdf",
"unit_type": "page",
"page": 1
},
"related_ids": []
}
]
}GET /api/objects/{file_id}/texts/preferredExample response:
{
"file_id": "sha256-test123",
"representation": "canonical",
"kind": "canonical_extracted_text",
"text": "Thermal calibration drift was reduced.",
"path": "objects/sha256-test123/text.txt"
}If editable text exists, it may become the preferred representation.
GET /api/objects/{file_id}/synthesesExample response:
{
"file_id": "sha256-test123",
"current_text": "This appears to be a technical report about thermal calibration drift.",
"current_toml": {
"path": {
"source_relpath": "reports/example.pdf"
},
"synthesis": {
"synthesis": "Technical report about thermal calibration drift.",
"doc_type": "technical report",
"quality": "default"
},
"details": {
"description": "This appears to be a technical report about thermal calibration drift."
}
},
"syntheses": [
{
"name": "current",
"text_path": "C:\\...\\.osii\\objects\\sha256-test123\\synth.txt",
"toml_path": "C:\\...\\.osii\\objects\\sha256-test123\\synth.toml",
"scope": "object"
}
]
}Text-span routes provide canonical grounding over object text stored in:
objects/<file_id>/text.txt
GET /api/text/objects/{file_id}/span?char_start=0&char_end=10Example response:
{
"file_id": "sha256-test123",
"char_start": 0,
"char_end": 10,
"text": "Thermal ca"
}Notes:
char_startandchar_endare required query parameterschar_endis effectively exclusive- spans are validated against canonical object text
- current invalid-range behavior returns a JSON error body with HTTP 200 rather than strict
400or404
GET /api/text/objects/{file_id}/span/context?char_start=0&char_end=10&context_chars=5Example response:
{
"file_id": "sha256-test123",
"char_start": 0,
"char_end": 10,
"match_text": "Thermal ca",
"before_text": "",
"after_text": "librat",
"window_start": 0,
"window_end": 15
}context_chars is optional and currently defaults to 200.
Enrichments are optional, derived, durable-on-disk outputs associated with scopes or objects.
They are not canonical extraction artifacts.
POST /api/enrichments/list
Content-Type: application/jsonSupported request variants:
- root
- folder
- collection
- object
Example request:
{
"scope_type": "object",
"file_id": "sha256-test123"
}Example response:
{
"scope": {
"scope_type": "object",
"file_id": "sha256-test123"
},
"enrichments": [
{
"name": "keywords--stats_keywords.json",
"kind": "file",
"relpath": "objects/sha256-test123/enrichments/keywords--stats_keywords.json"
}
]
}GET /api/enrichments/objects/{file_id}/{filename}This currently returns JSON-wrapped object enrichment payloads rather than arbitrary raw bytes.
Example response:
{
"file_id": "sha256-test123",
"filename": "keywords--stats_keywords.json",
"relpath": "objects/sha256-test123/enrichments/keywords--stats_keywords.json",
"data": {
"keywords": [
{
"term": "thermal",
"count": 1
}
],
"input_object_count": 1
}
}GET /api/search?q=thermal calibration drift&top_k=5Example response:
{
"query": "thermal calibration drift",
"top_k": 5,
"results": [
{
"faiss_id": 0,
"chunk_id": "chunk-sha256-test123-000001",
"file_id": "sha256-test123",
"source_relpath": "reports/example.pdf",
"chunk_method": "paragraph",
"chunk_index": 1,
"char_start": 0,
"char_end": 38,
"source_text_representation": "canonical",
"source_text_kind": "canonical_extracted_text",
"truncated": false,
"score": 0.8123
}
]
}The current public route is a simple semantic search endpoint.
Richer scope-aware search behavior exists in backend service logic, but should not be treated as public route behavior unless and until it is exposed as a formal route.
Search results may be ranked using derived embedding chunks.
They should be interpreted as retrieval results with canonical grounding information, not as canonical extraction segment identifiers.
Downstream consumers should use returned object identity and text-span grounding fields for navigation and text interaction.
In particular:
faiss_idis an internal retrieval identifierchunk_ididentifies a derived retrieval chunk, not a canonical manifest segmentfile_id,char_start, andchar_endare the grounding fields relevant for canonical text interaction
The backend also exposes discovery and orchestration routes for extraction, synthesis, run control, and embeddings.
These include:
GET /api/intake/readinessGET /api/browsePOST /api/resolveGET /api/extractorsGET /api/synthesizersGET /api/folder-synthesizersPOST /api/runsGET /api/runs/{run_id}GET /api/runs/{run_id}/logsPOST /api/embeddings/buildGET /api/embeddings/build/{job_id}GET /api/embeddings/meta
The existing implementation-aligned examples for these routes may be retained, with one update:
- embeddings metadata should mention chunking method and chunk manifest as part of current implementation detail
GET /artifact/{file_path:path}Example:
/artifact/objects/sha256-.../artifacts/artifact-000001.png
This route serves OSII-relative artifact paths only.
It is not arbitrary filesystem serving, and path traversal protections are enforced.
Compatibility read routes under /api/osii/... are still implemented.
New consumers should prefer:
/api/scopes/.../api/collections/.../api/objects/.../api/text/.../api/enrichments/...
Removed route families include:
/api/dashboard/...- dashboard/workbench HTML routes
See compatibility.md for migration-oriented notes.
Use this overview together with:
resource-model.mdsearch-semantics.mdcompatibility.mdopenapi.yaml
The Markdown documents explain behavior and conventions. The OpenAPI document should define exact schemas, parameters, and response contracts.