Downloading Files
To serve a file to your user, request a presigned download URL from Tenantbox. The URL points directly to Tenantbox storage — your server is not involved in the transfer.
How downloads work
Request download URL
Your server calls POST /api/storage/download/ with the file_path you saved at upload time.
Receive presigned URL
Tenantbox returns a time-limited URL that points directly to the file in Tenantbox storage.
Serve to your user
Redirect your user to the URL, use it in an <a href>, or fetch it server-side.
Endpoint
Request body
| Field | Type | Required | Description |
|---|---|---|---|
file_path | string | Required | The file_path returned when the file was uploaded. This is the permanent Tenantbox storage key. |
expires_in | integer | Optional | How long the download URL is valid for in seconds. Defaults to 3600 (1 hour). Max 86400 (24 hours). |
Response
| Field | Type | Description |
|---|---|---|
download_url | string | Presigned URL to the file. Valid for expires_in seconds. Serve this directly to your user. |
filename | string | Original filename of the file. |
content_type | string | MIME type of the file e.g. application/pdf, image/jpeg. |
size_bytes | integer | File size in bytes. |
expires_in | integer | Seconds until the download URL expires. |
Code examples
curl -X POST https://api.tenantbox.dev/api/storage/download/ \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"file_path": "projects/abc.../tenants/def.../xyz_contract.pdf",
"expires_in": 3600
}'{
"download_url": "https://xxx.r2.cloudflarestorage.com/multitenantstorage/projects/abc.../tenants/def.../xyz_contract.pdf?X-Amz-...",
"filename": "contract.pdf",
"content_type": "application/pdf",
"size_bytes": 204800,
"expires_in": 3600
}Important notes
URLs are time-limited
Download URLs expire after expires_in seconds. Don't cache them permanently — generate a fresh URL each time a user needs to access a file.
You need the file_path
The file_path is returned when you upload a file. Store it in your own database against the record it belongs to — Tenantbox does not provide a way to look up a file path after the fact without listing all tenant files.
Force file download
The presigned URL includes a ResponseContentDisposition: attachment header so browsers will download the file rather than open it inline. This is the default behaviour — no extra configuration needed.
File access is scoped to your project
Your API key can only generate download URLs for files belonging to your project's tenants. Attempting to access a file_path from another project returns a 404.
Error responses
{ "detail": "Unauthorized" }{ "detail": "File not found" }{ "detail": "File not found in storage" }Next — Deleting files
Learn how to permanently delete a file from storage and update tenant usage.