Skip to content

Versions

A file has one or more versions. Each is one upload: its bytes never change once it is available. The file’s current_version_no names the one that downloads, previews and search use. This page is for backends that replace a document’s content while keeping its id, its links and its history.

POST P/files/:file_id/versions takes { size, mime_type, content_sha256?, comment? } and answers the same upload ticket as a new file, bound to that file, with version_no one higher. The bytes go to the ticket’s URLs, and the completion (POST P/uploads/:upload_id/complete) makes the new version current. It is the same upload protocol, so the same code sends both.

  • It needs edit on the file. A file in review or approved accepts a new version only from someone with approve (status_locked); an archived file not at all.
  • With approvals on, a new version of a file that is not a draft reopens it as draft.
  • The new version is processed like a new file: its own renditions, its own metadata. The old versions keep theirs until they are pruned.
Route Does
GET P/files/:file_id/versions The versions, newest first: version_no, size, mime_type, created_by, created_at, comment, source, pinned, current
GET P/files/:file_id/versions/:version_no One version
POST P/files/:file_id/versions/:version_no/restore A new current version copied from an old one (source: "restore"). Nothing is lost
PATCH P/files/:file_id/versions/:version_no Pin it (pinned: true) or change its comment
DELETE P/files/:file_id/versions/:version_no Delete an old version. Never the current one (version_is_current), and nothing while the file is under a legal hold (file_on_hold)

Download or preview an old version with version=<n> on GET P/files/:file_id/download and GET P/files/:file_id/preview.

The application keeps at most max_versions versions per file (default 10, 1 to 100) and drops non-current versions older than version_retention_days. The oldest go first. The current version and pinned versions are never pruned, nor any version of a held file. A pruned version answers version_not_found. Every kept version counts against the quota.

Every file and folder carries revision, a number that grows with every change (metadata, a move, a new version). It is not the version number. Send it as If-Match on PATCH P/files/:file_id or PATCH P/folders/:folder_id: a stale one answers 412 revision_mismatch and changes nothing.

PATCH /api/v1/tenants/fitness-co/applications/fitness-app/files/01J9Z6S9Q5F5R6Y2W2GZ3B3K4D
If-Match: 5
Content-Type: application/json
{ "title": "Spring brochure, final" }

Locking a file for one editor (check-out and check-in) and opening documents in an online editor are coming. The routes are in the API already (POST P/files/:file_id/checkout, POST P/files/:file_id/checkin, DELETE P/files/:file_id/checkout, POST P/files/:file_id/edit-sessions) and answer 501 not_implemented until then. The file record already has the fields they will fill: lock (null today) and editable (false today).