Storage API Reference
Complete API reference for ZendBX Storage V3. All endpoints are project-scoped and use human-readable slugs.
💡Base URL:
https://api.zendbx.in/p/{project-slug}/storageAuthentication
All requests require authentication via JWT token or API key:
text
Authorization: Bearer YOUR_JWT_TOKEN
apikey: YOUR_ANON_KEYUse the anon key for client-side requests (with RLS enabled). Use the service role key for server-side operations.
Bucket Operations
Create Bucket
typescript
// SDK
const { data, error } = await db.storage.createBucket('documents', {
description: 'User documents',
isPublic: false,
});
// REST API
POST /p/{project-slug}/storage/buckets
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN
apikey: YOUR_ANON_KEY
{
"name": "documents",
"description": "User documents",
"is_public": false
}| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | required | Bucket name (auto-generates slug) |
| description | string | optional | Bucket description |
| is_public | boolean | optional | Allow public access (default: false) |
List Buckets
typescript
// SDK
const { data: buckets, error } = await db.storage.listBuckets();
// REST API
GET /p/{project-slug}/storage/buckets
Authorization: Bearer YOUR_TOKEN
apikey: YOUR_ANON_KEYGet Bucket Info
typescript
// SDK
const { data: bucket, error } = await db.storage.bucket('documents').info();
// REST API
GET /p/{project-slug}/storage/buckets/documents
Authorization: Bearer YOUR_TOKEN
apikey: YOUR_ANON_KEYDelete Bucket
typescript
// SDK
const { error } = await db.storage.deleteBucket('documents');
// REST API
DELETE /p/{project-slug}/storage/buckets/documents
Authorization: Bearer YOUR_TOKEN
apikey: YOUR_ANON_KEY⚠️Deleting a bucket does not delete its files. Files must be deleted separately.
File Operations
Upload File
typescript
// SDK - Browser
const bucket = db.storage.bucket('documents');
const file = event.target.files[0];
const { data, error } = await bucket.upload(file);
// SDK - Node.js
const buffer = fs.readFileSync('./report.pdf');
const { data, error } = await bucket.upload(buffer, 'report.pdf', {
contentType: 'application/pdf',
});
// REST API
POST /p/{project-slug}/storage/buckets/documents/upload
Content-Type: multipart/form-data
Authorization: Bearer YOUR_TOKEN
apikey: YOUR_ANON_KEY
file: [binary data]| Parameter | Type | Required | Description |
|---|---|---|---|
| file | File | Blob | Buffer | ArrayBuffer | required | File to upload |
| filename | string | optional | Override filename (defaults to file.name) |
| contentType | string | optional | MIME type (auto-detected for File objects) |
List Files
typescript
// SDK
const bucket = db.storage.bucket('documents');
const { data: files, error } = await bucket.list({
search: 'invoice',
sortBy: 'created_at',
sortDir: 'desc',
limit: 50,
offset: 0,
});
// REST API
GET /p/{project-slug}/storage/buckets/documents/files?search=invoice&sortBy=created_at&sortDir=desc
Authorization: Bearer YOUR_TOKEN
apikey: YOUR_ANON_KEY| Parameter | Type | Required | Description |
|---|---|---|---|
| search | string | optional | Search filename |
| sortBy | string | optional | created_at | size | filename |
| sortDir | string | optional | asc | desc |
| limit | number | optional | Results per page (default: 50) |
| offset | number | optional | Pagination offset |
Download File
typescript
// SDK
const bucket = db.storage.bucket('documents');
const response = await bucket.download('file-id');
const blob = await response.blob();
// REST API
GET /p/{project-slug}/storage/files/{file-id}/download
Authorization: Bearer YOUR_TOKEN
apikey: YOUR_ANON_KEYCreate Signed URL
typescript
// SDK
const bucket = db.storage.bucket('documents');
const { data, error } = await bucket.createSignedUrl('file-id', '1h');
// data.url → temporary download URL
// REST API
POST /p/{project-slug}/storage/files/{file-id}/signed-url
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN
apikey: YOUR_ANON_KEY
{
"expiry": "1h"
}| Parameter | Type | Required | Description |
|---|---|---|---|
| expiry | string | required | 5m | 15m | 1h | 24h | 7d |
Delete File
typescript
// SDK
const bucket = db.storage.bucket('documents');
await bucket.delete('file-id');
// Bulk delete
await bucket.bulkDelete(['file-1', 'file-2', 'file-3']);
// REST API
DELETE /p/{project-slug}/storage/files/{file-id}
Authorization: Bearer YOUR_TOKEN
apikey: YOUR_ANON_KEYGet Preview URL
typescript
// SDK (public buckets only)
const bucket = db.storage.bucket('public-assets');
const url = bucket.getPreviewUrl('logo.png');
// Returns: https://api.zendbx.in/p/demo/storage/files/{file-id}/preview💡Preview URLs only work for public buckets. For private buckets, use signed URLs.
Response Format
All successful responses return JSON:
json
{
"data": { ... },
"error": null
}Error responses:
json
{
"data": null,
"error": {
"message": "Bucket not found",
"code": "bucket_not_found",
"status": 404
}
}Error Codes
| Parameter | Type | Required | Description |
|---|---|---|---|
| 400 | Bad Request | optional | Invalid parameters |
| 401 | Unauthorized | optional | Invalid or missing authentication |
| 403 | Forbidden | optional | Permission denied |
| 404 | Not Found | optional | Project, bucket, or file not found |
| 409 | Conflict | optional | Bucket or file already exists |
| 413 | Payload Too Large | optional | File exceeds size limit |
| 415 | Unsupported Media Type | optional | File type not allowed |
| 500 | Internal Server Error | optional | Storage provider unavailable |
Rate Limits
Storage operations are subject to rate limits based on your plan:
- Free: 100 requests/minute
- Pro: 1,000 requests/minute
- Enterprise: Custom limits
💡Rate limit headers are included in responses:
X-RateLimit-Limit,X-RateLimit-Remaining, X-RateLimit-Reset
