Confluye
Endpoints

Files

Create, upload, scan, download, and request deletion of Workspace Files.

Endpoints under /api/v1/files (API keys) and /api/files (session; same handlers). JSON success uses api-contracts.v1: { ok: true, data, meta: { contractVersion: "api-contracts.v1" } }. Failure: { ok: false, error: { code, message } }. GET .../{id}/content is a raw byte stream, not that envelope.

Endpoints

MethodPathDescription
GET/api/v1/filesList files in the key workspace
POST/api/v1/filesCreate upload metadata (201)
GET/api/v1/files/{id}Get serialized metadata
DELETE/api/v1/files/{id}Request deletion (202)
PUT/api/v1/files/{id}/contentStore bytes (201 { blob })
GET/api/v1/files/{id}/contentDownload bytes (200 / 206)
POST/api/v1/files/{id}/completeVerify blob, scan (202 { file })

POST, PUT content, POST complete, and DELETE require Idempotency-Key.

Metadata and downloads require workspace.restricted.read (session controls can be stricter). GET .../{id}/content?preview=true verifies raster content and returns an inline PNG, JPEG, WebP or GIF. The default is an attachment. Both return Cache-Control: private, no-store and X-Content-Type-Options: nosniff. Preview rejects active formats such as SVG and HTML. DELETE returns 409 while a table record retains the file. Remove all table associations first; other owners and the existing GC retention policy remain in force.

List

GET /api/v1/files

QueryNotes
cursorOptional opaque base64url { createdAt, id }. Invalid: 400.
limitOptional. Default 50, integer 1–100. Else 400 request_malformed.

data: { files, nextCursor } (nextCursor null when no further page). Order: createdAt desc, id desc. No status filter.

Create upload

POST /api/v1/files — 201.

{ "name": "report.pdf", "mimeType": "application/pdf", "sizeBytes": 4 }
FieldNotes
nameRequired, trim, 1–255
mimeTypeRequired, trim, 1–255
sizeBytesInteger 0–104857600 (100 MiB)
sha256Optional 64 hex; stored lowercased

data: { file, uploadUrl, completeUrl }. URLs are {collection}/{id}/content|complete plus session workspaceId query when present.

Write readiness 503 on preview/production when Files is blocked. Replay of a successful create still 201 even if Files later becomes blocked (idempotency record). A new key is 503.

Get and delete

GET /api/v1/files/{id} — { file }.

DELETE /api/v1/files/{id} — 202 { file } with status: "deletion_requested" (or unchanged if already requested/deleted).

Deletion is refused while a table row or live image-change operation retains the file. For supported raster images, including server-validated images uploaded as application/octet-stream, live workflow execution, saved-run and pinned-output references also block deletion, including after the last table association is cleared. Generic octet-stream files do not receive this image-specific restriction. A reference whose lease has expired does not block deletion; remove permanent owning runs or pins to release their references.

Put content

PUT /api/v1/files/{id}/content — raw body required. Content-Length > 100 MiB → 413. data: { blob } (store stat: key, size, sha256). Only pending files.

Complete and scan

POST /api/v1/files/{id}/complete — body {} or { sizeBytes?, sha256? }. Completes then scans if pending_scan. 202 { file }.

File object (serialized)

FieldNotes
idUUID (or caller-supplied in service only; HTTP create uses random UUID)
namestring
mimeTypestring
sizeBytesnumber
sha25664 hex; "0"×64 until complete
statuspending | pending_scan | ready | quarantined | deletion_requested | deleted
createdAtISO-8601
updatedAtISO-8601

Storage keys, encryption, and scan rows are not serialized.

Content GET headers

HeaderValue
accept-rangesbytes
content-typeFile MIME
content-dispositionattachment; filename="…"
etag"sha256-{hex}"
content-lengthFull or range length
content-rangeOn 206: bytes start-end/total

Range must match bytes={start}-{end} (end optional). Other forms: 400. If start exists and end exceeds the file length, the response is 206 and ends at the file's last byte. A start outside the file or an end before the start returns 416.

Error map

HTTPerror.codeTypical cause
400idempotency_key_invalidMissing/invalid Idempotency-Key
400validation_failedBad create/complete JSON
400request_malformedBad limit/cursor/range/missing body
401authentication_requiredv1 bearer
403authorization_failedNon-workspace key
404resource_not_foundFile or blob missing in this workspace
409conflictWrong status, checksum/size mismatch, scan lease
409idempotency_replay_mismatchSame key, different body
413validation_failedOver 100 MiB
416validation_failedInvalid byte range
423conflictFile not ready (download)
503service_unavailableWrite readiness blocked
500internal_errorUnclassified

Use a file in a workflow

Upload and complete the file with this API, wait for ready, then pass its ID in input.fileInputs to the workflow execute endpoint. The execution verifies workspace ownership and resolves bytes only for consumers such as extraction or an HTTP binary/multipart body. Form and Webhook upload tokens cannot list or download Workspace Files. Inspector downloads use session authorization and the run's workspace.

Next steps