Documents
Documents belong to a workspace, optionally live inside a folder, and go
through an async ingestion pipeline (parsing → embedding → indexed,
or failed). Access to a document's contents is enforced inside the vector
query itself, not filtered afterward — a restricted document still shows up
in listings (existence is visible, Drive-style), but only a caller in its
ACL group can retrieve chunks or citations from it.
Upload document
Upload a file (multipart) and enqueue it for ingestion.
POST /api/v1/workspaces/{workspace_id}/documents · Auth: JWT, documents.upload
Request body
Content type: multipart/form-data.
| Parameter | Type | Required | Description |
|---|---|---|---|
file | file | Yes | The document file to upload. |
folder_id | string (uuid) | No | Target folder. Omit to upload into the workspace root. |
Sample request
curl -sX POST https://ragz.example.com/api/v1/workspaces/$WORKSPACE_ID/documents \
-H "Authorization: Bearer $TOKEN" \
-F "file=@employee-handbook.pdf" \
-F "folder_id=9f8e...-uuid"Sample response
{
"id": "d1e2...-uuid",
"workspace_id": "a1b2...-uuid",
"filename": "employee-handbook.pdf",
"status": "parsing",
"folder_id": "9f8e...-uuid",
"acl_group_ids": null,
"pinned": false,
"approved": false,
"version": 1
}Response fields
| Field | Type | Description |
|---|---|---|
id | string (uuid) | Document id. |
workspace_id | string (uuid) | Workspace the document belongs to. |
filename | string | Original filename. |
status | string | Ingestion status — starts parsing, moves through embedding to indexed, or failed. |
folder_id | string (uuid) | null | Folder the document was uploaded into. |
acl_group_ids | array | null | ACL group ids restricting the document. Admin/superadmin-only metadata — blanked to null for plain members, even for their own uploads. |
pinned | boolean | Whether the document is pinned. |
approved | boolean | Whether this version is approved. |
version | integer | Document version number. |
Notes
- The response's
statusstarts as the document enters the ingestion queue — pollGET /workspaces/{id}/documents(or your workspace's document list in the UI) to watch it move toindexed. acl_group_idsis admin-only metadata: a plain member getsnullhere even for their own uploads, unless they holdadmin/superadmin.
Upload size limits
Uploads route through two size caps depending on where they're sent
from: the general document upload endpoint above enforces the platform's
max_upload_mb setting (100 MB by default); the chat attachment
endpoint (POST /chats/{id}/attachments, see Chat) uses
the smaller interactive upload cap — 50 MB by default
(interactive_upload_mb), since attachments block an in-progress chat
turn. Both return 413 Payload Too Large over the limit.
List documents
List documents in a workspace.
GET /api/v1/workspaces/{workspace_id}/documents · Auth: JWT, documents.list
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
folder_id | string (uuid) | No | Filter to documents inside a specific folder. |
Notes
- Returns an array of document objects, same shape as the Upload document response above.
Get document file
Stream the original file bytes (citation viewer).
GET /api/v1/documents/{document_id}/file · Auth: JWT, documents.content.read
Delete document
Delete a document. Deletion is asynchronous — the route flips the document to deleting and returns 202 immediately; a worker propagates the removal to storage and the vector index.
DELETE /api/v1/documents/{document_id} · Auth: JWT, documents.delete
Sample request
curl -sX DELETE https://ragz.example.com/api/v1/documents/$DOCUMENT_ID \
-H "Authorization: Bearer $TOKEN"Sample response
202 Accepted
{ "status": "deletion scheduled" }Response fields
| Field | Type | Description |
|---|---|---|
status | string | Always "deletion scheduled". |
Notes
- Deletion is asynchronous — the route flips the document to
deletingand returns202immediately; a worker propagates the removal to storage and the vector index.
Reindex document
Re-run the parse→chunk→embed pipeline for one document, without a re-upload — useful after a parser or embedding-model change.
POST /api/v1/documents/{document_id}/reindex · Auth: JWT, documents.upload
Notes
- Only accepts documents currently in
indexedorfailedstate — a document mid-ingest can't be reindexed out from under itself.
Pin document
Pin/unpin a document.
PATCH /api/v1/documents/{document_id}/pin · Auth: JWT, documents.pin
Move document
Move a document to a different folder.
PATCH /api/v1/documents/{document_id}/move · Auth: JWT, documents.move
Set document ACL
Set the ACL group ids restricting a document.
PUT /api/v1/documents/{document_id}/acl · Auth: JWT, documents.acl.manage
Notes
- An empty/null list means unrestricted (any workspace member).
- Admin-only (
documents.acl.manage).
Approve document
Approve/unapprove a document version.
PUT /api/v1/documents/{document_id}/approved · Auth: JWT, documents.approve
Set document metadata
Set custom metadata field values.
PUT /api/v1/documents/{document_id}/metadata · Auth: JWT, documents.metadata.update
Create folder
Create a folder.
POST /api/v1/workspaces/{workspace_id}/folders · Auth: JWT, folders.create
Ensure folder path
Create a full folder path if missing.
POST /api/v1/workspaces/{workspace_id}/folders/ensure-path · Auth: JWT, folders.create
List folders
List folders in a workspace.
GET /api/v1/workspaces/{workspace_id}/folders · Auth: JWT, folders.read
Update folder
Rename/move a folder.
PATCH /api/v1/folders/{folder_id} · Auth: JWT, folders.update
Preview folder delete
Preview what a folder delete would cascade to.
GET /api/v1/folders/{folder_id}/delete-preview · Auth: JWT, folders.delete
Notes
- Reports the document and subfolder counts before you commit to the delete.
Delete folder
Delete a folder and cascade-delete its contents.
DELETE /api/v1/folders/{folder_id} · Auth: JWT, folders.delete
Notes
- Deleting a folder cascades to every document and subfolder beneath it.
- Each document's own ACL is still individually enforced during that cascade — not bypassed by the folder-level delete.
List metadata fields
List the workspace's custom metadata field schema.
GET /api/v1/workspaces/{workspace_id}/metadata-fields · Auth: JWT, documents.list
Create metadata field
Define a custom metadata field.
POST /api/v1/workspaces/{workspace_id}/metadata-fields · Auth: JWT, workspace.metadata.manage
Delete metadata field
Remove a metadata field.
DELETE /api/v1/metadata-fields/{field_id} · Auth: JWT, workspace.metadata.manage