Skip to main content
The Files endpoints give every organization a private knowledge base. Upload documents once and they become searchable through the same POST /v1/search call you already use for the web — scoped to your organization, invisible to everyone else. The flow is always the same four steps:
  1. PresignPOST /v1/files/presign returns a short-lived upload URL bound to your file’s exact size.
  2. UploadPUT the raw bytes to that URL. The bytes go straight to storage; they never pass through the API.
  3. IndexPOST /v1/files/index starts an indexing run; poll GET /v1/files/index/{sync_id} until it completes.
  4. Search — query with scope.indexes: ["workspace"] and your organization id as workspace_id.
The SDKs and CLI collapse steps 1–3 into a single call.

Searching your files

Workspace search runs through the ordinary search endpoint with a scope:
  • workspace_id is your organization id; the API verifies it matches the key’s organization, so no other tenant’s files are ever reachable.
  • Use "indexes": ["web", "workspace"] to blend web and file results in one response; workspace hits are tagged "index": "workspace" and ranked separately from web results.
  • Workspace results carry the same provenance handles as web results — doc_id, passages, and a source_uri pointing at the stored object — and can be opened with POST /v1/document by doc_id.

Managing files

Filenames are the identity: the API deals in the sanitized name echoed by presign, never in storage paths. Uploading the same filename again replaces the file (and re-indexing updates the document in place).

Indexing runs

POST /v1/files/index accepts { "mode": "incremental" } (default — new and changed files only) or { "mode": "full" } (reprocess everything). It answers 202 with a sync_id; poll GET /v1/files/index/{sync_id}:
Terminal states are completed and failed. The SDK/CLI upload helpers trigger one incremental run per upload call by default; when uploading many files, batch them (index=False / --no-index) and start one run at the end.

Supported types and limits

Unsupported types are rejected at presign time with 415 unsupported_file_type; oversized files with 413 file_too_large.

How presigned uploads work

The presign response’s url is a signed storage URL:
  • It authorizes exactly one PUT of exactly the declared size, for 15 minutes. A body of any other length is rejected by storage with 403.
  • Send no Authorization header on the PUT — the signature in the URL is the authorization, and your API key must never be sent to storage.
  • Treat the URL like a short-lived token: anyone holding it can upload that one object until it expires.