How to call TMS File endpoints — method, path, samples, and copyable curl. Set BASE_URL to your service origin (for example http://localhost:3000).
Placeholder: $BASE_URL
/api/v1/health-checksLiveness check — confirms the TMS File service process is responding.
Response
{
"message": "TMS-FILE is running"
}cURL
curl -sS "$BASE_URL/api/v1/health-checks"/api/v1/files/uploadmultipart/form-dataUpload a single file: create metadata and write bytes using the organization's active storage binding.
Request
multipart/form-data fields listed below.
file (binary, required)
organization_id (string, required)
sub_system (string, required)
original_name (string, optional — defaults to file name)
mime_type (string, optional)
upload_temp (boolean, optional — TEMP local-only file)Response
{
"file_id": "01HZX…",
"original_name": "sample.pdf",
"mime_type": "application/pdf",
"file_size": 12345,
"ext": "pdf",
"file_path": "1/oms/2026/09/26/…",
"sync_status": "PENDING",
"updated_at": "2026-09-26T10:00:00.000Z"
}cURL
curl -sS -X POST "$BASE_URL/api/v1/files/upload" \
-F "file=@./sample.pdf" \
-F "organization_id=1" \
-F "sub_system=oms" \
-F "original_name=sample.pdf" \
-F "mime_type=application/pdf"/api/v1/files/uploadmultipart/form-dataLifecycle mutations on an existing file_id: promote TEMP → THUMBNAIL, promote to ready, or replace the binary blob.
Request
multipart/form-data. make_as_thumbnail and make_as_ready are mutually exclusive.
file_id (string, required)
make_as_thumbnail (boolean — TEMP → THUMBNAIL; no binary)
make_as_ready (boolean — promote without or with binary)
file (binary — replace blob when status allows)
original_name / mime_type (optional with file)
Flags make_as_thumbnail and make_as_ready are mutually exclusive.Response
{
"file_id": "01HZX…",
"sync_status": "NONE",
"updated_at": "2026-09-26T10:05:00.000Z"
}cURL
curl -sS -X PUT "$BASE_URL/api/v1/files/upload" \
-F "file_id=01HZX…" \
-F "make_as_ready=true"/api/v1/files/batchmultipart/form-dataBatch upload (multipart items[]). All-or-nothing: insert DB rows in a transaction, then write files sequentially.
Request
Root fields plus indexed items[N].* parts.
organization_id (string, required)
sub_system (string, required)
items[N].file (binary, required)
items[N].original_name / mime_type (optional)
All-or-nothing: DB transaction then sequential disk writes.Response
[
{ "file_id": "…", "original_name": "a.pdf", "…": "…" },
{ "file_id": "…", "original_name": "b.png", "…": "…" }
]cURL
curl -sS -X POST "$BASE_URL/api/v1/files/batch" \
-F "organization_id=1" \
-F "sub_system=oms" \
-F "items[0].file=@./a.pdf" \
-F "items[0].original_name=a.pdf" \
-F "items[0].mime_type=application/pdf" \
-F "items[1].file=@./b.png" \
-F "items[1].original_name=b.png" \
-F "items[1].mime_type=image/png"/api/v1/files/{fileId}Read a file: LOCAL streams bytes; CLOUD redirects to a presigned URL. Use disposition=attachment to download.
Request
Path and optional query as below.
Path: fileId (ULID)
Query: disposition=attachment (optional)Response
LOCAL → 200 stream (file bytes)
CLOUD → 302 redirect to presigned URLcURL
curl -sS -L -o out.bin "$BASE_URL/api/v1/files/{fileId}"
# Download as attachment:
curl -sS -L -o out.bin "$BASE_URL/api/v1/files/{fileId}?disposition=attachment"/api/v1/files/{fileId}/{width}/{height}Square gallery variant: width must equal height and match the size whitelist. Streams WebP from variant cache or resizes on the fly.
Request
Path rules below. Non-square or non-whitelisted size → 400.
Path: fileId, width, height
Rules: width === height; size in whitelist: 200, 250, 300, 400, 500, 700, 1000
Outside whitelist or non-square → 400
Always streamed via tms-file (no R2 redirect)Response
200 image/webp (cached or resized on the fly)
Passthrough original when max edge ≤ requested sizecURL
curl -sS -o thumb.webp "$BASE_URL/api/v1/files/{fileId}/500/500"/api/v1/files/{fileId}Soft purge: sets purge_status = SYSTEM_PURGE. A background job deletes storage bytes then removes the DB row.
Request
Path parameter only.
Path: fileId (ULID)Response
{
"fileId": "01HZX…",
"deleted": true,
"storageLocation": "LOCAL",
"purgePending": true
}cURL
curl -sS -X DELETE "$BASE_URL/api/v1/files/{fileId}"/api/v1/storage-providersList active storage providers as { providerCode, providerName }.
Response
[
{ "providerCode": "R2", "providerName": "Cloudflare R2" }
]cURL
curl -sS "$BASE_URL/api/v1/storage-providers"/api/v1/organization-storage-bindings/createapplication/jsonCreate the organization's file storage binding (one active binding per organization).
Request
JSON body.
{
"organizationId": 1,
"organizationName": "Demo Org",
"storageProvider": "R2",
"syncEnabled": true
}Response
{
"id": 10,
"organizationId": 1,
"organizationName": "Demo Org",
"isActive": true,
"syncEnabled": true,
"storageProvider": "R2",
"effectiveFrom": "2026-09-26T10:00:00.000Z",
"effectiveTo": null
}cURL
curl -sS -X POST "$BASE_URL/api/v1/organization-storage-bindings/create" \
-H "Content-Type: application/json" \
-d '{
"organizationId": 1,
"organizationName": "Demo Org",
"storageProvider": "R2",
"syncEnabled": true
}'/api/v1/organization-storage-bindings/updateapplication/jsonUpdate the organization's active storage binding (including isActive to terminate or resume).
Request
JSON body.
{
"organizationId": 1,
"organizationName": "Demo Org",
"storageProvider": "R2",
"syncEnabled": true,
"isActive": true
}Response
{
"id": 10,
"organizationId": 1,
"isActive": true,
"syncEnabled": true,
"storageProvider": "R2"
}cURL
curl -sS -X PUT "$BASE_URL/api/v1/organization-storage-bindings/update" \
-H "Content-Type: application/json" \
-d '{
"organizationId": 1,
"organizationName": "Demo Org",
"storageProvider": "R2",
"syncEnabled": true,
"isActive": true
}'