Storage Buckets API
Complete API reference for managing storage buckets. Buckets are containers that organize and control access to your files.
Endpoints Overview
All bucket endpoints are scoped to an app using {app_slug} in the URL path.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/apps/{app_slug}/storage/buckets/ | List all buckets for an app |
| POST | /api/apps/{app_slug}/storage/buckets/ | Create a new bucket |
| GET | /api/apps/{app_slug}/storage/buckets/{slug}/ | Get bucket details |
| PATCH | /api/apps/{app_slug}/storage/buckets/{slug}/ | Update bucket |
| DELETE | /api/apps/{app_slug}/storage/buckets/{slug}/ | Delete bucket and all objects |
Bucket Model
Fields
| Field | Type | Description |
|---|---|---|
id | integer | Internal database ID |
uuid | UUID | Unique identifier for API references |
name | string | Human-readable bucket name |
slug | string | URL-safe identifier (auto-generated from name) |
visibility | string | Visibility level: "private" or "public" (default: "private") |
file_size_limit | integer | Maximum file size in bytes (default: 50MB) |
allowed_mime_types | array | List of allowed MIME types (empty = all allowed) |
app_category | string | App category/purpose: "assets" or "attachments" (required for creation) |
app | integer | App ID this bucket belongs to |
object_count | integer | Number of objects in bucket (read-only) |
created_at | datetime | Creation timestamp |
updated_at | datetime | Last update timestamp |
created_by | integer | User who created the bucket |
modified_by | integer | User who last modified the bucket |
Example Response
{
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "User Avatars",
"slug": "user-avatars",
"visibility": "public",
"file_size_limit": 5242880,
"allowed_mime_types": ["image/*"],
"app_category": "assets",
"app": 1,
"object_count": 42,
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-01-15T10:00:00Z",
"created_by": 1,
"modified_by": 1
}
List Buckets
Get all buckets, with optional filtering and search.
Request
GET /api/apps/{app_slug}/storage/buckets/
Authorization: Bearer YOUR_TOKEN
Query Parameters
| Parameter | Type | Description |
|---|---|---|
search | string | Search by name or slug |
ordering | string | Order by field (prefix with - for descending) |
visibility | string | Filter by visibility: "public" or "private" |
app_category | string | Filter by app category: "assets" or "attachments" |
page | integer | Page number for pagination |
page_size | integer | Number of results per page |
Note: Buckets are automatically filtered by app based on the {app_slug} in the URL path.
Examples
Basic List
curl https://your-api.com/api/apps/my-app/storage/buckets/ \
-H "Authorization: Bearer YOUR_TOKEN"
Search by Name
curl "https://your-api.com/api/apps/my-app/storage/buckets/?search=avatar" \
-H "Authorization: Bearer YOUR_TOKEN"
Order by Creation Date
curl "https://your-api.com/api/apps/my-app/storage/buckets/?ordering=-created_at" \
-H "Authorization: Bearer YOUR_TOKEN"
Public Buckets Only
curl "https://your-api.com/api/apps/my-app/storage/buckets/?visibility=public" \
-H "Authorization: Bearer YOUR_TOKEN"
Filter by App Category
curl "https://your-api.com/api/apps/my-app/storage/buckets/?app_category=assets" \
-H "Authorization: Bearer YOUR_TOKEN"
Response
{
"count": 3,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "User Avatars",
"slug": "user-avatars",
"visibility": "public",
"file_size_limit": 5242880,
"allowed_mime_types": ["image/*"],
"app": 1,
"object_count": 42,
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-01-15T10:00:00Z",
"created_by": 1,
"modified_by": 1
},
{
"id": 2,
"uuid": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"name": "Documents",
"slug": "documents",
"visibility": "private",
"file_size_limit": 52428800,
"allowed_mime_types": ["application/pdf", "application/msword", "text/*"],
"app": 1,
"object_count": 128,
"created_at": "2025-01-15T11:00:00Z",
"updated_at": "2025-01-15T11:00:00Z",
"created_by": 1,
"modified_by": 1
}
]
}
Create Bucket
Create a new storage bucket with optional constraints.
Request
POST /api/apps/{app_slug}/storage/buckets/
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json
{
"name": "User Avatars",
"app_category": "assets",
"visibility": "public",
"file_size_limit": 5242880,
"allowed_mime_types": ["image/*"]
}
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Human-readable bucket name |
app_category | string | Yes | App category/purpose: "assets" or "attachments" |
visibility | string | No | Visibility level: "private" or "public" (default: "private") |
file_size_limit | integer | No | Max file size in bytes (default: 52428800 = 50MB) |
allowed_mime_types | array | No | Allowed MIME types (default: [] = all allowed) |
Examples
Basic Bucket
curl -X POST https://your-api.com/api/apps/my-app/storage/buckets/ \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "My Files",
"app_category": "assets"
}'
Public Image Bucket (5MB limit)
curl -X POST https://your-api.com/api/apps/my-app/storage/buckets/ \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "User Avatars",
"app_category": "assets",
"visibility": "public",
"file_size_limit": 5242880,
"allowed_mime_types": ["image/jpeg", "image/png", "image/gif"]
}'
Document Bucket (All Image Types)
curl -X POST https://your-api.com/api/apps/my-app/storage/buckets/ \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Documents",
"app_category": "attachments",
"visibility": "private",
"file_size_limit": 52428800,
"allowed_mime_types": ["image/*", "video/*"]
}'
Private Bucket (Any File Type, 100MB)
curl -X POST https://your-api.com/api/apps/my-app/storage/buckets/ \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Large Files",
"app_category": "attachments",
"visibility": "private",
"file_size_limit": 104857600,
"allowed_mime_types": []
}'
Response (201 Created)
{
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "User Avatars",
"slug": "user-avatars",
"app_category": "assets",
"visibility": "public",
"file_size_limit": 5242880,
"allowed_mime_types": ["image/*"],
"app": 1,
"object_count": 0,
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-01-15T10:00:00Z",
"created_by": 1,
"modified_by": null
}
Slug Generation
The slug is auto-generated from the name:
- Converted to lowercase
- Spaces replaced with hyphens
- Special characters removed
Examples:
- "User Avatars" →
user-avatars - "My Documents & Files" →
my-documents-files - "Team Projects 2025" →
team-projects-2025
App Categories
The app_category field categorizes buckets by their purpose, enabling selective operations like app exports. This field is required when creating a bucket.
Available Types
| Type | Value | Description | Use Cases |
|---|---|---|---|
| Assets | "assets" | App-related files that should be exported with the app | • UI components • App resources • Static files • Templates |
| Attachments | "attachments" | User-uploaded files that remain with the workspace | • User documents • Profile pictures • Message attachments • Form uploads |
When to Use Each Type
Use "assets" when:
- Files are part of the app's functionality
- Files should be exported when the app is exported
- Files are created by app developers/designers
- Files are shared across users
Use "attachments" when:
- Files are uploaded by end users
- Files should stay in the workspace when exporting apps
- Files are user-specific or session-specific
- Files are dynamic user content
Example Scenario: App Export
When exporting an app for transfer or backup:
# Get all asset buckets to export
GET /api/apps/{app_slug}/storage/buckets/?app_category=assets
# These buckets and their files will be included in the app export
The attachments buckets are intentionally excluded, keeping user data separate from app structure.
Get Bucket
Retrieve details of a specific bucket.
Request
GET /api/apps/{app_slug}/storage/buckets/{slug}/
Authorization: Bearer YOUR_TOKEN
Example
curl https://your-api.com/api/apps/my-app/storage/buckets/user-avatars/ \
-H "Authorization: Bearer YOUR_TOKEN"
Response (200 OK)
{
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "User Avatars",
"slug": "user-avatars",
"visibility": "public",
"file_size_limit": 5242880,
"allowed_mime_types": ["image/*"],
"app_category": "assets",
"app": 1,
"object_count": 42,
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-01-15T10:00:00Z",
"created_by": 1,
"modified_by": 1
}
Update Bucket
Partially update a bucket's configuration. Only PATCH is supported (not PUT).
Request
PATCH /api/apps/{app_slug}/storage/buckets/{slug}/
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json
{
"visibility": "private",
"file_size_limit": 10485760
}
Updatable Fields
| Field | Type | Description |
|---|---|---|
name | string | Bucket display name |
app_category | string | App category/purpose: "assets" or "attachments" |
visibility | string | Visibility level: "private" or "public" |
file_size_limit | integer | Max file size in bytes |
allowed_mime_types | array | Allowed MIME types |
Note: slug, app, uuid cannot be changed.
Examples
Make Bucket Private
curl -X PATCH https://your-api.com/api/apps/my-app/storage/buckets/user-avatars/ \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"visibility": "private"}'
Increase Size Limit to 10MB
curl -X PATCH https://your-api.com/api/apps/my-app/storage/buckets/user-avatars/ \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"file_size_limit": 10485760}'
Update Allowed MIME Types
curl -X PATCH https://your-api.com/api/apps/my-app/storage/buckets/documents/ \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"allowed_mime_types": [
"application/pdf",
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
]
}'
Rename Bucket
curl -X PATCH https://your-api.com/api/apps/my-app/storage/buckets/user-avatars/ \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Profile Pictures"}'
Response (200 OK)
{
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "User Avatars",
"slug": "user-avatars",
"visibility": "private",
"file_size_limit": 10485760,
"allowed_mime_types": ["image/*"],
"app_category": "assets",
"app": 1,
"object_count": 42,
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-01-15T12:30:00Z",
"created_by": 1,
"modified_by": 1
}
Delete Bucket
Delete a bucket and all its objects. This operation is irreversible.
Request
DELETE /api/apps/{app_slug}/storage/buckets/{slug}/
Authorization: Bearer YOUR_TOKEN
Behavior
- Deletes all files from cloud storage (batch operation)
- Deletes all object records from database (cascade)
- Deletes the bucket record
Example
curl -X DELETE https://your-api.com/api/apps/my-app/storage/buckets/user-avatars/ \
-H "Authorization: Bearer YOUR_TOKEN"
Response (204 No Content)
{
"success": true,
"message": "Bucket \"User Avatars\" and all objects deleted successfully",
"status_code": 204
}
Error Response (500 Internal Server Error)
If deletion fails (e.g., storage unavailable):
{
"success": false,
"message": "Failed to delete bucket \"User Avatars\"",
"status_code": 500
}
MIME Type Patterns
The allowed_mime_types field supports exact matches and wildcards.
Exact Match
{
"allowed_mime_types": [
"image/jpeg",
"image/png",
"image/gif"
]
}
Only these specific types are allowed.
Wildcard Match
{
"allowed_mime_types": [
"image/*",
"video/*"
]
}
Allows all image and video types:
image/jpeg✓image/png✓image/svg+xml✓video/mp4✓application/pdf✗
Common Patterns
Images Only
{"allowed_mime_types": ["image/*"]}
Documents
{
"allowed_mime_types": [
"application/pdf",
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
]
}
Media Files
{"allowed_mime_types": ["image/*", "video/*", "audio/*"]}
Text Files
{"allowed_mime_types": ["text/*"]}
No Restrictions
{"allowed_mime_types": []}
Validation Rules
When creating or updating a bucket, the allowed_mime_types field is validated to ensure only valid MIME type patterns are stored.
Valid Formats
Each MIME type entry must follow one of these patterns:
- Exact type:
type/subtype(e.g.,image/png,application/pdf) - Wildcard type:
type/*(e.g.,image/*,video/*) - Universal:
*/*(allows all types)
The validation follows RFC 6838 MIME type conventions with the following rules:
- Type and subtype must start with an alphanumeric character
- Type and subtype can contain letters, numbers, hyphens, plus signs, and dots
- Must include a forward slash (
/) separator - Wildcards (
*) are only allowed in the subtype position
Valid Examples
✅ These will pass validation:
{
"allowed_mime_types": [
"image/png",
"image/jpeg",
"application/pdf",
"image/*",
"video/*",
"text/plain",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
]
}
❌ These will be rejected:
{
"allowed_mime_types": [
"image/", // Missing subtype
"image", // Missing slash and subtype
"*/png", // Wildcard only allowed in subtype position
"", // Empty string
"/png", // Missing type
"image/*pdf" // Invalid format after wildcard
]
}
Error Messages
If validation fails, you'll receive a clear error message:
{
"allowed_mime_types": [
"Invalid MIME type format: ['image/', 'image']. Valid formats: 'image/png', 'image/*', 'application/pdf', etc."
]
}
Best Practices
- Use wildcards for flexibility:
["image/*"]instead of listing every image format - Combine exact and wildcards:
["image/*", "application/pdf"]for images + PDFs - Empty list for no restrictions:
[]allows all MIME types - Validate before upload: Invalid patterns will be rejected at bucket creation/update time
- Test your patterns: Ensure your MIME type patterns match the files you intend to upload
File Size Limits
Recommended limits based on use case:
| Use Case | Limit | Bytes |
|---|---|---|
| Avatars/Icons | 2 MB | 2097152 |
| Photos | 5 MB | 5242880 |
| Documents | 10 MB | 10485760 |
| High-res Images | 25 MB | 26214400 |
| General Files | 50 MB | 52428800 |
| Large Files | 100 MB | 104857600 |
For files >100MB, increase the bucket's file_size_limit when creating the bucket. Note that very large files may be subject to server memory constraints.
Authentication & Permissions
All bucket operations require authentication:
- JWT Token Required: Include
Authorization: Bearer YOUR_TOKENheader in all requests - App-Scoped: Buckets are associated with your app
- Secure Access: Private buckets require authentication for all operations
- Public Buckets: When marked as public, files can be accessed without authentication
Best Practices
Naming Conventions
Good Names:
- User Avatars →
user-avatars - Project Documents →
project-documents - Team Photos 2025 →
team-photos-2025
Avoid:
- Generic names: "Files", "Data"
- Special characters: "My@Files", "Docs#1"
- Very long names (keep under 50 characters)
Bucket Organization
By Purpose:
avatars- User profile picturesdocuments- User documentsmedia- Photos, videosexports- Generated reports
By Visibility:
public-assets- Publicly accessible filesprivate-files- Authenticated access only
By Type:
images- All image filesvideos- All video filesaudio- All audio files
By App Category:
- Use
app_category: "assets"for app-related files (UI components, templates, static resources) - Use
app_category: "attachments"for user-uploaded content (documents, photos, form uploads) - This distinction is crucial for app export functionality - assets are exported with the app, attachments remain in the workspace
Security
-
Use Private Buckets by Default
- Only make buckets public if necessary
- Consider signed URLs for temporary access
-
Set Appropriate Size Limits
- Prevents abuse and excessive storage costs
- Match limits to expected file types
-
Restrict MIME Types
- Prevent unexpected file uploads
- Reduce security risks
-
Regular Audits
- Review bucket configurations
- Monitor storage usage
- Check for unused buckets
Visibility & Access Control
Overview
The visibility field controls who can access objects in a bucket. Each bucket has a default visibility level that objects inherit, but individual objects can override this setting for fine-grained control.
Visibility Levels
| Level | Value | Description | Access Rules |
|---|---|---|---|
| Private | "private" | Default visibility | • Requires authentication • Only file owner or staff can access • Most secure option |
| Public | "public" | Publicly accessible | • No authentication required for downloads • Anyone with the URL can access • Upload/delete still requires authentication |
How It Works
Bucket-Level Visibility (Default)
When you create a bucket, its visibility setting determines the default access level for all objects:
# Create a public bucket
POST /api/apps/{app_slug}/storage/buckets/
{
"name": "Public Images",
"visibility": "public" # All objects will be public by default
}
Object-Level Overrides
Individual objects can override the bucket's default visibility. See Object Visibility for details.
Example Scenario:
Bucket: "marketing-assets" (visibility: "public")
├─ logo.png (visibility: null) → Effective: public (inherits)
├─ banner.jpg (visibility: null) → Effective: public (inherits)
└─ draft-logo.png (visibility: "private") → Effective: private (overrides!)
In this example:
- The bucket is public, so most assets are publicly accessible
- But
draft-logo.pngoverrides withvisibility: "private"to keep it restricted - This solves the problem of one private file in an otherwise public bucket
Access Control Rules
Public Objects
- ✅ GET/Download: Anyone with the URL (no auth required)
- ❌ POST/Upload: Requires authentication + ownership
- ❌ DELETE: Requires authentication + ownership
- ❌ PATCH/Update: Requires authentication + ownership
Private Objects
- ✅ GET/Download: Owner or staff only (requires auth)
- ✅ POST/Upload: Owner only (requires auth)
- ✅ DELETE: Owner only (requires auth)
- ✅ PATCH/Update: Owner only (requires auth)
Examples
Public Bucket for Website Assets
POST /api/apps/{app_slug}/storage/buckets/
{
"name": "Website Assets",
"visibility": "public",
"allowed_mime_types": ["image/*", "video/*"]
}
Use case: Product images, logos, marketing materials that anyone can view.
Private Bucket for User Documents
POST /api/apps/{app_slug}/storage/buckets/
{
"name": "User Documents",
"visibility": "private",
"file_size_limit": 104857600 # 100MB
}
Use case: Tax documents, contracts, personal files that require authentication.
Mixed Visibility (Public Bucket with Private Exceptions)
# 1. Create public bucket
POST /api/apps/{app_slug}/storage/buckets/
{
"name": "Product Images",
"visibility": "public"
}
# 2. Upload public image (inherits bucket visibility)
PUT /api/apps/{app_slug}/storage/buckets/product-images/objects/released/product-1.jpg
Content-Type: image/jpeg
<binary data>
# 3. Upload private image (overrides bucket visibility)
PUT /api/apps/{app_slug}/storage/buckets/product-images/objects/unreleased/secret-product.jpg
Content-Type: multipart/form-data
file=<binary>
visibility="private" # This object will be private despite public bucket
Security Best Practices
- Default to Private: Use
"visibility": "private"unless you have a specific reason for public access - Audit Public Buckets: Regularly review public buckets to ensure no sensitive data is exposed
- Use Object Overrides: For mostly-public buckets, use object-level
visibility: "private"for exceptions - Combine with MIME Types: Restrict
allowed_mime_typesfor public buckets to prevent unwanted file types - Monitor Access: Track who uploads to public buckets using the
created_byfield
Changing Visibility
You can change a bucket's visibility at any time:
# Make a public bucket private
PATCH /api/apps/{app_slug}/storage/buckets/website-assets/
{
"visibility": "private"
}
⚠️ Important: Changing bucket visibility affects all objects that inherit from it. Objects with explicit visibility settings are not affected.
Related Documentation
- Objects API Reference - File operations and object-level visibility
- Storage Quickstart - Getting started guide
- Advanced Features - Search, copy, batch operations
- Storage Overview - Architecture and concepts