Skip to content

Files

The public API uses a presign + finalize flow for uploads. The API never touches your bytes directly — it only signs MinIO URLs and verifies the result. Required scope: files:write.

POST /v1/files/presign-upload

Reserves a file_id and returns a presigned MinIO PUT URL.

Request

bash
curl -X POST \
  -H "Authorization: Bearer ff_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "filename": "budget.xlsx",
    "size": 524288,
    "mime": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
  }' \
  https://fileforge-api.aldrickb.app/v1/files/presign-upload

Response

json
{
  "file_id": "9f6c...8e",
  "bucket": "fileforge-inputs",
  "storage_key": "<user_id>/2026/05/07/9f6c...8e-budget.xlsx",
  "upload_url": "https://minio.lan/.../X-Amz-Signature=…",
  "expires_in": 900
}

The upload_url expires in 15 minutes. The signed URL carries the exact Content-Length you declared — uploading a different size will fail with a SigV4 mismatch from MinIO.

size is checked against your tier's max_file_mb. Free is 10 MB (and free can't use the API anyway); Pro is 500 MB; Enterprise is 2 GB.

PUT to upload_url

Use the URL exactly as returned, with the same Content-Type you declared:

bash
curl --upload-file budget.xlsx \
     -H "Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" \
     "$UPLOAD_URL"

A successful PUT returns 200 with no body. Anything else is a fatal upload error — don't finalize it.

POST /v1/files/{id}/finalize

Verifies the object, runs magic-byte detection, and streams the file through ClamAV. On success, returns the persisted file record.

bash
curl -X POST \
  -H "Authorization: Bearer ff_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "storage_key": "<user_id>/2026/05/07/9f6c...8e-budget.xlsx",
    "original_name": "budget.xlsx",
    "declared_mime": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
  }' \
  https://fileforge-api.aldrickb.app/v1/files/9f6c...8e/finalize

Successful response (201):

json
{
  "id": "9f6c...8e",
  "original_name": "budget.xlsx",
  "mime_type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  "size_bytes": 524288,
  "expires_at": "2026-05-14T12:34:56.000Z",
  "created_at": "2026-05-07T12:34:56.000Z"
}

If magic-byte detection disagrees with declared_mime, finalize returns 422 mime_mismatch and the object is deleted. If ClamAV finds something, finalize returns 422 malware_detected, the object is deleted, and a file.quarantined audit-log entry is written.

DELETE /v1/files/{id}

Wipes the object and the row. Required scope: files:delete.

bash
curl -X DELETE \
  -H "Authorization: Bearer ff_live_…" \
  https://fileforge-api.aldrickb.app/v1/files/9f6c...8e

204 No Content on success. 404 if the file ID doesn't belong to your account or has already been deleted.

Built solo on dedicated metal.