Sign in

Storage Files API Reference

REST API for Cosmos Storage: uploads (direct and resumable), versions, downloads, browsing, folders, moves, bulk operations, ZIP, ACLs, upload-time redaction, and metrics.

storage
storagefilesfoldersuploadsaclredactionapi

Updated 2026-11-03

Verified 2026-11-03

Storage is the Cosmos document management system (DMS). Files and folders are both items; every item has an owner, an access level, and optional per-user ACL entries. For architecture and configuration, see Storage Service.

Every endpoint except health checks requires Authorization: Bearer YOUR_TOKEN and X-Org-Id: YOUR_ORG_ID. A missing token returns 401; a missing or invalid X-Org-Id returns 400. X-Project-Id is optional and attributes the action to a project in Recent Activity. Errors use {"error": "BadRequest", "status": 400, "message": "..."}. See API Conventions.

Local base URL: http://localhost:8107. All paths below are under /api/v1/.

Endpoint Summary

MethodPathPurpose
POSTitems/upload/Upload a file (multipart, up to 300 MB)
POSTitems/upload-session/startStart a resumable direct-to-cloud upload (up to 6 GiB)
POSTitems/import-url/Import a file from a URL
GETitems/Browse and search items
GET, PATCH, DELETEitems/{id}/Item detail, update, delete
GETitems/{id}/stats/Folder statistics
GET, POSTitems/{id}/versions/List versions; upload a new version
GETitems/{id}/content/Download content
POSTitems/{id}/move/Move an item
POSTitems/folders/Create a folder
GETitems/bulk-fetch/, items/bulk-fetch-by-path/Fetch many items with signed URLs
POSTitems/bulk-access-level/Change access level for up to 1,000 items
POSTitems/check-permissions/Check the caller's permissions on up to 100 items
GET, PUT, DELETEitems/{id}/acl/Read, replace, or clear ACL entries
POSTitems/{id}/zip/, items/{id}/unzip/Background ZIP and unzip
POSTitems/upload-redacted/, items/upload-redacted-zip/Upload with PII redaction
GET, DELETEredaction/jobs/{id}/Redaction job status; cancel
POSTredaction/jobs/{id}/apply/Apply a reviewed redaction
GETredaction/batch/{id}/ZIP redaction batch status
GETmetrics/Organization file, folder, and size totals
GET/health/Health check (no auth, no /api/v1 prefix)

Item Object

FieldDescription
idItem UUID
org_idOwning organization
name, descriptionName (up to 128 characters) and description (up to 512)
parent_id, materialized_path, levelPosition in the folder tree
is_directorytrue for folders
size, latest_version_sizeSize in bytes
latest_version, latest_version_mime_typeLatest file version details
owner_idOwning user
access_levelprivate, public_read, or public_write
total_folders, total_filesChild counts for folders
created_at, created_by, updated_at, updated_byAudit fields

Uploads

Direct upload

POST /api/v1/items/upload/
Content-Type: multipart/form-data
FieldRequiredDescription
fileYesFile content (up to 300 MB)
nameNoItem name; defaults to the file name
parent_id or parent_pathNoDestination folder
force_create_pathNoCreate missing folders in parent_path
force_upload_new_versionNoAdd a version if an item with this name exists
descriptionNoDescription
access_levelNoDefault private
owner_idNoSuperusers only

Returns 201 with the item and a version object that includes a signed_url.

.m4a files are stored as audio/mp4. Storage checks that file content matches the declared type and rejects mismatches.

Resumable upload sessions

Large files upload directly to cloud storage, then Storage verifies and promotes them in the background.

  1. Start — POST /api/v1/items/upload-session/start

    json
    {
      "filename": "recording.mp4",
      "content_type": "video/mp4",
      "declared_size": 2147483648,
      "parent_path": "/Recordings",
      "force_create_path": true,
      "access_level": "private"
    }
    

    Optional fields: kind (normal or redaction), name, parent_id, force_upload_new_version, description, owner_id, redaction, and target_item_id. declared_size can be up to 6 GiB.

    Returns 201:

    json
    {
      "session_id": "SESSION_UUID",
      "session_token": "YOUR_SESSION_TOKEN",
      "status": "initiated",
      "kind": "normal",
      "upload_url": "https://...",
      "method": "PUT",
      "headers": {"...": "..."},
      "protocol": "azure_block",
      "expires_at": "2026-11-03T12:00:00Z",
      "chunk_size": 8388608
    }
    

    protocol is azure_block, gcs_resumable, or local_put depending on the backend.

  2. Upload — send the bytes to upload_url using method and headers. Call POST .../upload-session/{id}/uploading when you begin, and POST .../upload-session/{id}/refresh-url if the URL expires.

  3. Complete — POST /api/v1/items/upload-session/{id}/complete, optionally with {"checksum": "<sha256 hex>"}. Returns 202; the checksum is verified asynchronously.

  4. Poll — GET /api/v1/items/upload-session/{id} until status is completed (or failed, aborted, expired). Statuses move through initiated, uploading, and completing. POST .../upload-session/{id}/abort cancels it.

Import from URL

POST /api/v1/items/import-url/ with source_url and the same destination fields as a direct upload.

Versions and Downloads

MethodPathDescription
GETitems/{id}/versions/List versions
POSTitems/{id}/versions/Upload a new version (multipart file)
GETitems/{id}/content/?version=NDownload content; omit version for the latest
GET /api/v1/items/?parent_id=FOLDER_UUID&search=report&file_type=pdf&sort_by=updated_at&sort_order=desc&page_size=20
ParameterDescription
parent_idFolder to list; omit for the root
is_directoryOnly folders or only files
searchName search
recursiveInclude descendants
file_typezip, pdf, docx, xls, csv, images, or others
mime_typeOne or more MIME types
access_level, owner_idFilters (owner_id accepts several values)
sort_byname, created_at, updated_at, or size
sort_orderasc or desc
page_sizeDefault 20, maximum 100
next_cursorCursor from the previous page
json
{"results": [{"id": "ITEM_UUID", "name": "Q3 report.pdf", "is_directory": false, "...": "..."}], "next_cursor": "...", "page_size": 20}

Results only include items the caller can view.

Item Operations

MethodPathBody or parameters
GETitems/{id}/—
PATCHitems/{id}/name, description, access_level, owner_id, applies_to_children
DELETEitems/{id}/Soft delete; ?force=true deletes a non-empty folder
GETitems/{id}/stats/Folder statistics
POSTitems/{id}/move/{"new_parent_id": "FOLDER_UUID"}
POSTitems/folders/name (1–128 characters), parent_id, description, access_level, owner_id

Bulk Operations

Bulk fetch. GET /api/v1/items/bulk-fetch/?item=UUID&item=UUID:2 returns items with signed URLs; append :version to pin a version. GET /api/v1/items/bulk-fetch-by-path/?item=/Reports/q3.pdf does the same by path. Items the caller cannot view are skipped. Administrators can set signed_url_expiry_minutes.

Bulk access level.

POST /api/v1/items/bulk-access-level/
json
{"items": [{"item_id": "ITEM_UUID", "access_level": "public_read", "update_children": true}]}

Up to 1,000 items. Returns {"updated_count": 1, "failed_items": []}.

Permission check.

POST /api/v1/items/check-permissions/
json
{"item_ids": ["ITEM_UUID_1", "ITEM_UUID_2"]}

Up to 100 IDs. Returns one permission object per item (view, update, delete, manage ACL). The frontend uses this to decide which actions to show; results are cached for 5 minutes.

Access Control

Each ACL entry grants or denies one user specific actions on an item. A user has at most one allow and one deny entry per item. allow is evaluated before deny, and RBAC *_all permissions bypass deny entries.

PUT /api/v1/items/{id}/acl/
json
{
  "acls": [
    {
      "user_id": "USER_UUID",
      "effect": "allow",
      "can_view": true,
      "can_update": true,
      "can_delete": false,
      "can_manage_acl": false,
      "applies_to_children": true
    }
  ]
}

PUT replaces the item's entries and returns {"success": true, "message": "...", "affected_count": 1, "acls": [...]}. GET returns the current entries; DELETE removes them.

ZIP and Unzip

POST /api/v1/items/{id}/zip/ archives a folder and POST /api/v1/items/{id}/unzip/ extracts a ZIP file. Both return 202 Accepted and run in the background. Only items the caller can view are included, and the archive type is validated before extraction.

Upload-Time Redaction

Storage can remove PII from documents and images as they are uploaded.

MethodPathDescription
POSTitems/upload-redacted/Multipart file plus config (JSON), redaction_mode (native or azure), and use_org_default. Returns 202 with a job.
POSTitems/upload-redacted-zip/Redact every supported file in a ZIP. Returns 202 with a batch.
GETredaction/jobs/{id}/Job status and results
POSTredaction/jobs/{id}/apply/Apply a reviewed redaction. Returns 202.
DELETEredaction/jobs/{id}/Cancel a job
GETredaction/batch/{id}/ZIP batch status

Large uploads can also be redacted through an upload session with "kind": "redaction".

Metrics

GET /api/v1/metrics/
json
{"org_id": "YOUR_ORG_ID", "total_files": 1280, "total_folders": 96, "total_size": 73400320}

Limits

LimitValue
Direct upload (items/upload/)300 MB
Resumable upload session6 GiB
ZIP redaction300 MB per entry; 10 times that in total
Azure document PII analysis10 MB per request; larger PDFs are split into parts of about 8 MB
Bulk access-level update1,000 items
Permission check100 items
Browse page size100

Testing

bash
curl -s -X POST http://localhost:8107/api/v1/items/upload/ \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Org-Id: YOUR_ORG_ID" \
  -F "file=@./report.pdf" \
  -F "parent_path=/Reports" \
  -F "force_create_path=true"

curl -s "http://localhost:8107/api/v1/items/?search=report" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Org-Id: YOUR_ORG_ID"