Skip to main content

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.

MethodEndpointDescription
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

FieldTypeDescription
idintegerInternal database ID
uuidUUIDUnique identifier for API references
namestringHuman-readable bucket name
slugstringURL-safe identifier (auto-generated from name)
visibilitystringVisibility level: "private" or "public" (default: "private")
file_size_limitintegerMaximum file size in bytes (default: 50MB)
allowed_mime_typesarrayList of allowed MIME types (empty = all allowed)
app_categorystringApp category/purpose: "assets" or "attachments" (required for creation)
appintegerApp ID this bucket belongs to
object_countintegerNumber of objects in bucket (read-only)
created_atdatetimeCreation timestamp
updated_atdatetimeLast update timestamp
created_byintegerUser who created the bucket
modified_byintegerUser 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

ParameterTypeDescription
searchstringSearch by name or slug
orderingstringOrder by field (prefix with - for descending)
visibilitystringFilter by visibility: "public" or "private"
app_categorystringFilter by app category: "assets" or "attachments"
pageintegerPage number for pagination
page_sizeintegerNumber 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

FieldTypeRequiredDescription
namestringYesHuman-readable bucket name
app_categorystringYesApp category/purpose: "assets" or "attachments"
visibilitystringNoVisibility level: "private" or "public" (default: "private")
file_size_limitintegerNoMax file size in bytes (default: 52428800 = 50MB)
allowed_mime_typesarrayNoAllowed 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

TypeValueDescriptionUse 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

FieldTypeDescription
namestringBucket display name
app_categorystringApp category/purpose: "assets" or "attachments"
visibilitystringVisibility level: "private" or "public"
file_size_limitintegerMax file size in bytes
allowed_mime_typesarrayAllowed 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

  1. Deletes all files from cloud storage (batch operation)
  2. Deletes all object records from database (cascade)
  3. 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:

  1. Exact type: type/subtype (e.g., image/png, application/pdf)
  2. Wildcard type: type/* (e.g., image/*, video/*)
  3. 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

  1. Use wildcards for flexibility: ["image/*"] instead of listing every image format
  2. Combine exact and wildcards: ["image/*", "application/pdf"] for images + PDFs
  3. Empty list for no restrictions: [] allows all MIME types
  4. Validate before upload: Invalid patterns will be rejected at bucket creation/update time
  5. 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 CaseLimitBytes
Avatars/Icons2 MB2097152
Photos5 MB5242880
Documents10 MB10485760
High-res Images25 MB26214400
General Files50 MB52428800
Large Files100 MB104857600

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_TOKEN header 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 pictures
  • documents - User documents
  • media - Photos, videos
  • exports - Generated reports

By Visibility:

  • public-assets - Publicly accessible files
  • private-files - Authenticated access only

By Type:

  • images - All image files
  • videos - All video files
  • audio - 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

  1. Use Private Buckets by Default

    • Only make buckets public if necessary
    • Consider signed URLs for temporary access
  2. Set Appropriate Size Limits

    • Prevents abuse and excessive storage costs
    • Match limits to expected file types
  3. Restrict MIME Types

    • Prevent unexpected file uploads
    • Reduce security risks
  4. 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

LevelValueDescriptionAccess 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.png overrides with visibility: "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

  1. Default to Private: Use "visibility": "private" unless you have a specific reason for public access
  2. Audit Public Buckets: Regularly review public buckets to ensure no sensitive data is exposed
  3. Use Object Overrides: For mostly-public buckets, use object-level visibility: "private" for exceptions
  4. Combine with MIME Types: Restrict allowed_mime_types for public buckets to prevent unwanted file types
  5. Monitor Access: Track who uploads to public buckets using the created_by field

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.