Skip to main content
Hcfs • 2 mins read

GET /download/{ss58}/{folder_hash}/{file_id}

GET /download/{ss58}/{folder_hash}/{file_id}

Stream the stored ciphertext for one file, along with the metadata needed to drive a progress bar and to maintain the three-tree sync state.

Authentication

Authorization: Bearer <token>. The token's resolved SS58 must match the {ss58_address} path segment. See auth.md.

Request

Method and path

GET /download/{ss58_address}/{folder_hash}/{file_id}

Path parameters

NameFormatNotes
ss58_addressstringOwner's SS58 address
folder_hash16-char hexFirst 16 chars of SHA-256(folder_label)
file_id64-char hexHex encoding of path_hash (BLAKE3 of the relative path)

Headers

Authorization: Bearer <token>
Range: bytes=<start>-<end> # optional, for partial content

Query parameters

None.

Response — success

Status

StatusWhen
200 OKFull blob returned
206 Partial ContentRange: header was honored

Response headers

HeaderMeaning
Content-LengthCiphertext bytes. Drives HTTP progress. May be omitted when the storage layer cannot report a length — clients must handle chunked transfer.
X-Size-BytesPlaintext bytes. Display this in the UI.
X-Revision-Id64-char hex — the file's current revision
X-Revision-Sequ64 — monotonic revision sequence
X-File-IdEcho of the URL's {file_id}
X-Ss58-AddressEcho of the URL's {ss58_address}
X-Folder-HashEcho of the URL's {folder_hash}
Accept-Rangesbytes — partial-content is supported
Content-RangeSet on 206 Partial Content responses

Body

Raw ciphertext bytes in the HCFS chunked wire format. See upload.md for the framing layout and the per-chunk nonce derivation.

Response — errors

Shared envelope shape in errors.md.

Statuserror codeCause
400invalid_file_idfile_id is not valid 64-char hex
401unauthorizedMissing / bad bearer token
403forbiddenToken resolves to a different SS58 than the path
404not_foundNo file at this (ss58_address, folder_hash, path_hash)
500storage_inconsistencyMetadata row exists but the ciphertext blob is missing — retry with backoff; re-surface to logs if persistent

Example

curl -H "Authorization: Bearer $SS58" \
-o "file.enc" \
-D "headers.txt" \
"$SERVER/download/$SS58/$FOLDER_HASH/$FILE_ID"

# Range request (resumable download)
curl -H "Authorization: Bearer $SS58" \
-H "Range: bytes=1048576-" \
-o "file.enc.part2" \
"$SERVER/download/$SS58/$FOLDER_HASH/$FILE_ID"

Notes

  • To decrypt the returned bytes, you need the per-file encryption_key derived from the same mnemonic that was used to sign the upload.
  • Content-Length and X-Size-Bytes differ because encryption adds framing overhead (24-byte base nonce + 4-byte count + 20 bytes per chunk). Use X-Size-Bytes for any user-facing file-size UI, and Content-Length only for HTTP transfer progress.
  • The file_id is stable across revisions — only the content, revision_id, and revision_seq change.