ZeroDB · File Storage API
S3-compatible storage — per project, one key
Every ZeroDB project gets S3/MinIO-backed object storage. Upload, download, stream, and presign URLs — private by default, public on demand. No separate S3 bucket or credential setup.
Private by default
Files are private to your project. Generate presigned URLs for time-limited public access — no key exposure.
No S3 setup
Storage is provisioned automatically with your project. Same X-API-Key as vectors, tables, and memory.
Presign, don't proxy
Generate presigned GET or PUT URLs to let clients access files directly — offload bandwidth from your server.
API reference
Base URL: https://api.ainative.studio Auth: X-API-Key: <your-project-api-key>
List files
# Public developer path (paginated)
GET /api/v1/public/zerodb/{project_id}/database/files
X-API-Key: <your-project-api-key>
# Response:
# {
# "files": [...],
# "total": 42,
# "page": 1,
# "page_size": 20,
# "has_more": true
# }
# Project path (same data, project-scoped)
GET /api/v1/projects/{project_id}/filesUpload a file
POST /api/v1/projects/{project_id}/files/upload
X-API-Key: <your-project-api-key>
Content-Type: multipart/form-data
# Form fields:
# file — the file bytes
# metadata — optional JSON string with key/value tags
# Returns:
# {
# "file_id": "...",
# "filename": "report.pdf",
# "content_type": "application/pdf",
# "size_bytes": 102400,
# "project_id": "...",
# "created_at": "..."
# }Download & stream
# File metadata
GET /api/v1/projects/{project_id}/files/{file_id}
# Download (returns a presigned URL or redirect)
GET /api/v1/projects/{project_id}/files/{file_id}/download
# Stream bytes directly (server-side proxying)
GET /api/v1/projects/{project_id}/files/{file_id}/contentGenerate a presigned URL
POST /api/v1/projects/{project_id}/files/{file_id}/presigned-url
X-API-Key: <your-project-api-key>
{
"operation": "get", # "get" | "put"
"expires_in": 3600 # seconds; default 3600
}
# Returns:
# { "url": "https://...", "expires_at": "..." }Delete & stats
# Delete a file
DELETE /api/v1/projects/{project_id}/files/{file_id}
# Storage summary (totals by content type)
GET /api/v1/projects/{project_id}/files/stats/summary
# Response:
# {
# "total_files": 42,
# "total_bytes": 10485760,
# "by_content_type": {
# "application/pdf": { "count": 12, "bytes": 5242880 },
# "image/png": { "count": 30, "bytes": 5242880 }
# }
# }Patterns & anti-patterns
Patterns
- Presign, don't proxy. Return a presigned URL to the client so large files bypass your server entirely.
- Tag files with metadata. Store content-type, owner, and purpose in the optional metadata field for easier filtering.
- Check stats/summary before billing audits. The summary endpoint gives a fast per-type breakdown without listing every file.
- Stream for server-side processing. Use /content to pipe bytes directly into your processing pipeline.
Anti-patterns
- Storing your key in the client. Project API keys are server-side secrets — generate presigned URLs instead.
- Proxying all file traffic. Large file downloads through your backend waste compute — presign and redirect.
- Unlimited presign expiry. Long-lived presigned URLs are effectively public. Set short expiry and regenerate on demand.
- No content-type on upload. Without a MIME type, the stats summary is less useful and browser rendering may break.
Get the File Storage API Workbook — Upload, Presign & Serve
A free PDF guide: upload files, generate presigned URLs, serve publicly, and manage storage — step by step.
Frequently asked questions
What is the ZeroDB File Storage API?
File Storage is S3/MinIO-backed object storage per project. Files are private by default, with optional public serving and presigned URL generation. Access via two path families: the public developer path (/api/v1/public/zerodb/{project_id}/database/files) for listing, and the project path (/api/v1/projects/{project_id}/files/*) for upload, download, and management.
How do I upload a file?
POST to /api/v1/projects/{project_id}/files/upload with multipart/form-data containing the file and optional metadata fields. The response includes the file_id which you use for all subsequent operations on that file.
How do presigned URLs work?
POST to /api/v1/projects/{project_id}/files/{file_id}/presigned-url with a custom expiry and operation (get or put). The API returns a time-limited URL that lets clients directly access or upload to the file without exposing your API key. Use presigned URLs to serve large files directly from storage rather than proxying through your server.
Can files be served publicly?
Files are private by default. You can make individual files publicly accessible or generate presigned URLs with a custom expiry. The /api/v1/projects/{project_id}/files/{file_id}/content endpoint streams bytes directly for server-side proxying.
How do I see storage usage?
GET /api/v1/projects/{project_id}/files/stats/summary returns totals by content type — number of files, total bytes, and a breakdown by MIME type. For project-level storage quota vs tier limits, use GET /api/v1/projects/{project_id}/usage.
Is there a separate sign-up or S3 bucket setup needed?
No. File Storage is included in every ZeroDB project. Use the same X-API-Key you use for vectors, tables, and memory — no separate S3 credentials or bucket configuration required. Create a temporary project in one call via POST /api/v1/public/instant-db.