Storage
Every project gets S3-compatible object storage. You organize files into buckets, and each bucket can be private (access through your app / signed URLs) or public (files served directly over a permanent URL). Use it for avatars, uploads, exports, static assets, and more.
Concepts
| Term | Meaning |
|---|---|
| Bucket | A top-level container for files. Created public or private. |
| Object | A single file, addressed by its path (e.g. user-123/avatar.png). |
| Folder | A path prefix. There are no real directories — a / in the path groups files. avatars/2026/pic.png lives in the avatars/2026/ folder. |
| Public bucket | Objects are readable by anyone at a permanent URL, no token. Good for assets. |
| Private bucket | Objects require your app's session or a time-limited signed URL. |
Buckets
Manage buckets with bf.storage.
import { createClient } from 'basefyio-js'
const bf = createClient()
// Create a bucket (private by default)
await bf.storage.createBucket('avatars')
// Create a PUBLIC bucket
await bf.storage.createBucket('assets', { public: true })
// List all buckets
const { data: buckets } = await bf.storage.listBuckets()
// [{ name, public, objectCount, totalSize, createdAt }]
// Change visibility (public ↔ private)
await bf.storage.updateBucket('avatars', { public: true })
// Delete a bucket (must be empty)
await bf.storage.deleteBucket('avatars')Bucket names are 3–63 characters, lowercase letters, numbers and hyphens, and can't start or end with a hyphen.
Uploading files
Scope operations to a bucket with bf.storage.from(bucket). The path may include / to place the file in a folder — parent folders are created implicitly.
const bucket = bf.storage.from('avatars')
// Upload (browser File/Blob, Uint8Array or ArrayBuffer)
const { data, error } = await bucket.upload(
'user-123/avatar.png', // path — the "user-123/" folder is implied
file,
{ contentType: 'image/png' }
)
// Uploading to the same path overwrites the existing object.Max upload size is 50 MB per file via the API. For folders, see the dashboard's Upload folder action below.
Listing files & folders
// List the bucket root
const { data } = await bf.storage.from('avatars').list()
// List inside a folder (prefix)
const { data } = await bf.storage.from('avatars').list('user-123/')
// Entries with a "prefix" field are folders; entries with "name" are files:
// { name, size, lastModified, etag } | { prefix: 'user-123/' }Downloading files
// Download as a Blob
const { data: blob } = await bf.storage.from('avatars').download('user-123/avatar.png')
// Delete one or more files
await bf.storage.from('avatars').remove([
'user-123/avatar.png',
'user-123/old.png',
])Public links & signed URLs
Public bucket — objects are served directly, no token, at a permanent URL:
https://storage.basefyio.com/<internal-bucket>/<path>From the dashboard (Storage tab) you can copy the public link for the whole bucket, any folder, or an individual file — and toggle a bucket public/private. For a private bucket, generate a time-limited signed URL instead:
// Temporary signed URL for a private object (default 1 hour, max 7 days)
const { data } = await bf.storage.from('reports').createSignedUrl(
'q1/summary.pdf',
{ expiresIn: 3600 } // seconds
)
// data.url data.expiresInA folder/bucket public link is the base URL for its objects — appending a file path yields a working link. Object storage has no anonymous directory listing, so the base URL alone won't list contents.
In the dashboard
The Storage tab adds workflows beyond the SDK:
- New folder — create an empty folder in the current location.
- Upload folder — upload a whole local folder, preserving its structure; if files already exist you're asked to overwrite or skip them.
- Public link — copy a shareable URL for a public bucket, folder, or file.
- Toggle a bucket between public and private.
REST API
All routes are under https://api.basefyio.com/api/projects/:projectId/storage and require your API key / session.
| Method | Path | Description |
|---|---|---|
| GET | /buckets | List buckets |
| POST | /buckets | Create bucket { name, public } |
| PATCH | /buckets/:bucket | Set visibility { public } |
| DELETE | /buckets/:bucket | Delete bucket |
| GET | /buckets/:bucket/public-url?path= | Public URL (public buckets) |
| POST | /buckets/:bucket/folders | Create folder { path } |
| GET | /buckets/:bucket/objects?prefix= | List objects/folders |
| POST | /buckets/:bucket/objects?path= | Upload (multipart file) |
| POST | /buckets/:bucket/objects/exists | Which of { paths } exist |
| GET | /buckets/:bucket/objects/download?path= | Download a file |
| GET | /buckets/:bucket/objects/url?path=&expiry= | Signed URL |
| DELETE | /buckets/:bucket/objects | Delete { paths } |