Skip to main content
POST
/
namespaces
/
{namespace_name}
/
files
Upload File
curl --request POST \
  --url http://localhost:8080/namespaces/{namespace_name}/files \
  --header 'Content-Type: <content-type>' \
  --data '
{
  "files": [
    {}
  ],
  "files[].path": "<string>",
  "files[].force_reindex": true,
  "files[].{metadata}": "<any>"
}
'
{
  "status": "success",
  "message": "File upload started. Poll file job status for progress.",
  "job_id": "job-1fad681df00046c0a7f950daeb52f120",
  "namespace_name": "my-documents",
  "total": 1,
  "ingesting": 1,
  "skipped": []
}

Overview

Upload one or more files from a server-visible path into a text namespace. The server reads the file from disk (no HTTP multipart body), chunks it with the bundled Python chunker, generates batch summaries every 100 chunks, embeds each chunk, and stores them for search.
Path-based upload only (v1). Copy or mount files under ~/.moorcheh/uploads on the host (mounted read-only as /uploads in the container). API requests must use container paths such as /uploads/document.pdf.
Supported extensions: .pdf, .docx, .xlsx, .pptx, .txt, .csv, .md, .json. The job runs asynchronously. Poll File job status with the returned job_id.

Path parameters

namespace_name
string
required
Target text namespace.

Headers

Content-Type
string
required
Must be application/json

Body

files
array
required
Non-empty array of file objects.
files[].path
string
required
Absolute path inside the server container. Use /uploads/... for files under the default upload mount.
files[].force_reindex
boolean
default:"false"
When true, re-chunk and replace the index even if file_size and file_mtime match a previous upload.
files[].{metadata}
any
Optional extra keys on each file object are merged into chunk metadata (for example "department": "engineering").

File identity and deduplication

  • file_id is server-generated: first 16 hex chars of sha256(namespace + NUL + absolute_path).
  • Skip re-upload when the same path already exists with the same file_size and file_mtime, unless force_reindex is true.
  • Chunk ids: {file_id}_chunk_{index}. Summary ids: {file_id}_summary_{batch}.
  • Each content chunk metadata includes summary_chunk_id (bare id, e.g. abc_summary_0) linking to its batch summary.

Request example

curl -X POST "http://localhost:8080/namespaces/my-documents/files" \
  -H "Content-Type: application/json" \
  -d '{
    "files": [
      {
        "path": "/uploads/document.pdf",
        "department": "engineering",
        "force_reindex": false
      }
    ]
  }'

Response fields

status
string
"success" when the upload job started or all files were skipped.
message
string
Human-readable result.
job_id
string
Async job id when at least one file is uploading. Poll File job status.
namespace_name
string
Target namespace.
total
number
Number of file entries in the request.
ingesting
number
Files accepted into the upload job.
skipped
array
Files skipped as already indexed (same size/mtime). Each entry includes file_id, absolute_path, and message.
{
  "status": "success",
  "message": "File upload started. Poll file job status for progress.",
  "job_id": "job-1fad681df00046c0a7f950daeb52f120",
  "namespace_name": "my-documents",
  "total": 1,
  "ingesting": 1,
  "skipped": []
}

Errors

HTTPCause
400Empty files, unsupported extension, path outside /uploads, file not found, non-text namespace
404Namespace not found
Item limit is checked during the upload job (not at POST time). If exceeded, the job finishes with status: "failed" and last_error like "Item limit exceeded: max …, current …, requested … new items." — poll File job status.

Important notes

  • Use container paths (/uploads/...) in direct API calls — not Windows or macOS host paths.
  • The CLI moorcheh upload-file accepts a host path under ~/.moorcheh/uploads and converts it for you.
  • Upload indexes content only; deleting the index later does not remove the file on disk.