Uploading & Downloading
Uploading Files
Inline Upload (Small Files)
For small files, include the content directly as base64:
curl -X POST https://api.travila.ai/api/v1/storage/gateway/upload-file \
-H "X-API-Key: sk_your_key_here" \
-H "X-On-Behalf-Of: user_123" \
-H "Content-Type: application/json" \
-d '{
"folder_path": "/documents",
"file_name": "notes.txt",
"content": "SGVsbG8gV29ybGQ=",
"content_type": "text/plain",
"tags": ["notes", "work"],
"metadata": {
"source": "api-upload"
}
}'
Inline upload is deprecated — it ships the full bytes synchronously through the gateway, so it's slow for large files. Prefer the pre-signed flow below for all new integrations.
Pre-Signed Upload (Large Files)
For anything larger than a couple of megabytes, use the 3-step pre-signed flow: get a URL, upload the bytes directly to the storage backend, then register the file.
Step 1: Get the upload URL (size_bytes is required — it is checked against your quota and enforced by the storage backend)
curl -X POST https://api.travila.ai/api/v1/storage/gateway/generate-upload-url \
-H "X-API-Key: sk_your_key_here" \
-H "X-On-Behalf-Of: user_123" \
-H "Content-Type: application/json" \
-d '{
"folder_path": "/media",
"file_name": "video.mp4",
"content_type": "video/mp4",
"size_bytes": 52428800,
"expires_seconds": 3600
}'
Response:
{
"url": "https://storage.googleapis.com/bucket/...",
"file_id": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
"full_path": "/media/video.mp4",
"required_headers": {
"content-type": "video/mp4",
"x-goog-content-length-range": "0,52428800"
}
}
Step 2: Upload directly to the URL. Send every header from required_headers verbatim — they are part of the signature:
curl -X PUT "https://storage.googleapis.com/bucket/..." \
-H "Content-Type: video/mp4" \
-H "x-goog-content-length-range: 0,52428800" \
--data-binary @video.mp4
Step 3: Register the file. This makes it visible to list-files, get-file-metadata, and generate-download-url:
curl -X POST https://api.travila.ai/api/v1/storage/gateway/register-uploaded-file \
-H "X-API-Key: sk_your_key_here" \
-H "X-On-Behalf-Of: user_123" \
-H "Content-Type: application/json" \
-d '{
"file_id": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
"folder_path": "/media",
"file_name": "video.mp4"
}'
Registration is idempotent — retrying returns the already-registered file with "registered": false. Registering before the upload finished returns 404.
Downloading Files
Generate a pre-signed download URL:
curl -X POST https://api.travila.ai/api/v1/storage/gateway/generate-download-url \
-H "X-API-Key: sk_your_key_here" \
-H "X-On-Behalf-Of: user_123" \
-H "Content-Type: application/json" \
-d '{
"file_id": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
"expires_seconds": 3600
}'
Response:
{
"url": "https://storage.googleapis.com/bucket/...",
"file": {
"name": "notes.txt",
"path": "/documents/notes.txt",
"size_bytes": 11,
"content_type": "text/plain"
}
}
Use response_content_disposition to force a download with a specific filename:
{
"file_id": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
"response_content_disposition": "attachment; filename=my-notes.txt"
}