Skip to main content

Documents API

RouteMethodPurpose
/api/docGETSigned document URL
/api/doc-upload-sessionPOSTAllocate a document row and signed upload token
/api/ingest-docPOSTEnqueue extraction/embedding for an uploaded document
/api/document-inventoryGETAdmin/lead inventory of indexed documents

Upload flow​

  1. POST /api/doc-upload-session allocates the documents catalog row and a signed upload token — the browser uploads directly to storage using that token, not through this API. show_on_portal (default true) records the intent only (metadata.show_on_portal); false creates the row with internal_only = true. A contracts_sow file stays restricted and never records the intent (20 Oct 2026).
  2. POST /api/ingest-doc { document_id } then enqueues indexing. Before it does, a staff upload (source_system: "upload") with that intent, not restricted, not Internal and not contracts_sow gets released_to_client, portal_visible, and release_status: "released", but only once the stored object is confirmed in Storage. An upload that never finishes stays off the portal; a retry or later reindex never re-releases or overrides a release decision.
{ "document_id": "document-uuid" }

This route is intentionally durable-only: extraction, embedding, and atomic publication all run in Trigger.dev (sable.document.backfill-index-batch), not inline in the request handler — the request only validates access and enqueues the work. Rate-limited via SABLE_INGEST_RATE_LIMIT (default 12/min).

GET /api/doc​

Returns a signed URL for one document. Enforced by the same access rules across every document surface:

  • A valid Supabase session is required.
  • Restricted documents (contracts, SOWs) require admin/lead.
  • Non-leads must be a member of the document's project.

GET /api/document-inventory​

Admin/lead only. Every indexed document plus contract/SOW extraction health flags — buildDocumentInventory (in _deliverable_authoring.js) is shared with the deliverable-drafting pipeline's evidence-collection step, so this inventory and what a deliverable draft can actually cite are always the same list.

Where the code lives​

  • web/api/doc.js, doc-upload-session.js, ingest-doc.js, document-inventory.js
  • web/api/_doc_upload.js, _document_ingest.js, _ingestion_pipeline.js, _deliverable_authoring.js
  • trigger/documents.ts
  • docs-site/docs/reference/search-indexing.md — the retrieval side of this pipeline