Knowledge Documents
Upload, inspect, archive and restore knowledge documents through MCP or REST, including safe automated refreshes.
Knowledge documents are files the bot can search for factual answers. They use the same ingestion, chunking and embedding pipeline whether uploaded from the dashboard, MCP or REST. Supported formats are TXT, CSV, Markdown, PDF, DOCX, XLSX and XLS. Real files must be non-empty and at most 25 MiB; CSV imports support up to 1,000 rows and spreadsheet imports up to 10,000 rows.
MCP tools
Use list_documents to find current documents with file IDs and indexing status;
pass includeArchived: true to include retained archives. upload_document accepts inline
text for TXT, CSV and Markdown. For a real file, call
create_document_upload_url, PUT the original bytes to its temporary URL,
then call finalize_document_upload with the returned fileId.
archive_document disables the document's context while retaining its file and
embedding chunks. Find archived documents with
list_archived_configuration_resources using resourceType: "document", and
recover them with restore_document.
REST operations
All paths below start with /rest/v1 and require X-API-Key. Use the
REST reference for complete request and response
schemas. Copilot and MCP can discover these endpoints in the Documents
group with list_rest_api_operations.
| Method | Path | Purpose |
|---|---|---|
| GET | /documents?businessSlug=shop | List active documents; add includeArchived=true to include retained archives |
| GET | /documents/{id}?businessSlug=shop | Read one document, its download URL and indexing status, including archives |
| POST | /documents | Upload inline {businessSlug, filename, content} for TXT, CSV or Markdown, up to 500,000 characters |
| POST | /documents/uploads | Reserve a direct upload with {businessSlug, filename} |
| POST | /documents/uploads/{fileId}/finalize | Validate and ingest uploaded bytes; body is {businessSlug} |
| DELETE | /documents/{id}?businessSlug=shop | Recoverably archive the exact document |
| POST | /documents/{id}/restore | Restore the retained document and its previous context enablement; body is {businessSlug} |
Documents are scoped to the API key's organization and requested business.
Cross-business files cannot be finalized or used to archive another business's
knowledge. Archived businesses remain readable but reject mutations. Python
recurring jobs can use their injected OCTOCOM_ORG_API_KEY and
OCTOCOM_API_BASE_URL with the same endpoints.
Upload reservations return {data: {fileId, presignedUrl, uploadHeaders}}.
PUT the original bytes, without an Octocom API key, to presignedUrl using
the exact uploadHeaders, including x-ms-blob-type: BlockBlob. Do not encode
a PDF, Word document or spreadsheet as inline text. Finalization checks size,
format and file safety before ingestion. Repeated finalization of the same
fileId returns its existing document, even if it was archived; it does not
create a second document or restore it.
Upload and download URLs are credentials. Keep them out of logs and version
control. Private download links expire at urlExpiresAt; request document
details again when you need a fresh one. Responses containing these links use
Cache-Control: no-store.
Safely refresh a document
Uploading the same filename creates a new document. There is no implicit overwrite or deletion. Keep the old document active until the new one is ready:
- Fetch and validate the complete new source content. Save the old document ID.
- Upload the replacement and save its returned document ID. Binary uploads require the direct-byte upload and finalization steps above.
- Poll the replacement with GET until
data.statusisready. - Archive the saved old document ID. Do not select it by filename alone.
Ingestion parses the file before returning, but indexing continues asynchronously. Document status has four possible values:
| Status | Meaning |
|---|---|
indexing | Extracted content is not fully chunked and embedded yet |
ready | All extracted context elements are indexed and embedding chunks exist |
empty | The file produced no searchable context; keep the old document |
archived | The document is retained but its archived context is disabled |
indexing includes work that has not completed, including failed background
indexing. Use a bounded polling deadline and inspect failures if it does not
become ready. A timeout or ingestion error is not a reason to archive the old
snapshot. Record IDs in durable organization storage so a later run can resume
or inspect an uncertain upload, rather than creating another replacement.
For example, after uploading a replacement through REST:
import requests
import time
def wait_for_document(business_slug, document_id, timeout=40):
url = f"{OCTOCOM_API_BASE_URL}/rest/v1/documents/{document_id}"
deadline = time.monotonic() + timeout
while time.monotonic() < deadline:
response = requests.get(
url,
params={"businessSlug": business_slug},
headers={"X-API-Key": OCTOCOM_ORG_API_KEY},
timeout=10,
)
response.raise_for_status()
document = response.json()["data"]
if document["status"] == "ready":
return document
if document["status"] in {"empty", "archived"}:
raise RuntimeError("Replacement is not searchable; keep the old document")
time.sleep(1)
raise TimeoutError("Replacement is not ready; keep the old document")Archival and restoration are idempotent. Archival preserves the original enablement of each context element, and restoration reuses the retained chunks without another download or embedding request. Document writes are included in configuration history; API request audit also retains execution-token identity for Python-triggered requests. File contents and signed URLs are not copied into document change snapshots.