Overview
The Supabase Storage API provides RESTful endpoints for managing files in your storage buckets. Upload, download, list, and delete files with simple HTTP requests.
Base URL
Storage endpoints are available at:
https://<PROJECT_REF>.supabase.co/storage/v1/
Buckets
List Buckets
Get all storage buckets.
curl 'https://<PROJECT_REF>.supabase.co/storage/v1/bucket' \
-H "apikey: YOUR_ANON_KEY" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Response
[
{
"id" : "avatars" ,
"name" : "avatars" ,
"public" : true ,
"created_at" : "2024-03-04T10:00:00.000Z" ,
"updated_at" : "2024-03-04T10:00:00.000Z"
},
{
"id" : "documents" ,
"name" : "documents" ,
"public" : false ,
"created_at" : "2024-03-04T10:00:00.000Z" ,
"updated_at" : "2024-03-04T10:00:00.000Z"
}
]
Unique identifier for the bucket.
Whether the bucket is publicly accessible.
Get Bucket
Get details of a specific bucket.
curl 'https://<PROJECT_REF>.supabase.co/storage/v1/bucket/avatars' \
-H "apikey: YOUR_ANON_KEY" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Create Bucket
Create a new storage bucket.
curl -X POST 'https://<PROJECT_REF>.supabase.co/storage/v1/bucket' \
-H "apikey: YOUR_ANON_KEY" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "avatars",
"public": true,
"file_size_limit": 52428800,
"allowed_mime_types": ["image/png", "image/jpeg"]
}'
Unique name for the bucket.
Whether the bucket is publicly accessible.
Maximum file size in bytes (default: 50MB).
List of allowed MIME types. If null, all types are allowed.
Update Bucket
Update bucket configuration.
curl -X PUT 'https://<PROJECT_REF>.supabase.co/storage/v1/bucket/avatars' \
-H "apikey: YOUR_ANON_KEY" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"public": false,
"file_size_limit": 10485760
}'
Delete Bucket
Delete an empty bucket.
curl -X DELETE 'https://<PROJECT_REF>.supabase.co/storage/v1/bucket/avatars' \
-H "apikey: YOUR_ANON_KEY" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Empty Bucket
Delete all files in a bucket.
curl -X POST 'https://<PROJECT_REF>.supabase.co/storage/v1/bucket/avatars/empty' \
-H "apikey: YOUR_ANON_KEY" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Objects
Upload File
Upload a file to a storage bucket.
curl -X POST 'https://<PROJECT_REF>.supabase.co/storage/v1/object/avatars/public/avatar1.png' \
-H "apikey: YOUR_ANON_KEY" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: image/png" \
-H "cache-control: 3600" \
--data-binary '@/path/to/file.png'
The bucket name (in the URL path).
The file path within the bucket (in the URL path).
Cache control header value (in seconds).
Response
{
"Key" : "avatars/public/avatar1.png" ,
"Id" : "e8c0e3c1-5f3a-4b9e-8f1a-2c3d4e5f6a7b"
}
Upload with Upsert
Overwrite existing files by adding the x-upsert header.
curl -X POST 'https://<PROJECT_REF>.supabase.co/storage/v1/object/avatars/public/avatar1.png' \
-H "apikey: YOUR_ANON_KEY" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: image/png" \
-H "x-upsert: true" \
--data-binary '@/path/to/file.png'
When true, overwrites existing file with the same path.
Download File
Download a file from storage.
curl 'https://<PROJECT_REF>.supabase.co/storage/v1/object/avatars/public/avatar1.png' \
-H "apikey: YOUR_ANON_KEY" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-o avatar1.png
The file will be downloaded with appropriate caching headers.
Transform images on-the-fly (resize, format conversion).
curl 'https://<PROJECT_REF>.supabase.co/storage/v1/render/image/authenticated/avatars/public/avatar1.png?width=400&height=400&resize=cover&format=webp' \
-H "apikey: YOUR_ANON_KEY" \
-o avatar1_thumb.webp
Resize mode: cover, contain, fill.
Output format: webp, jpeg, png, avif.
Quality (1-100) for lossy formats.
List Files
List all files in a folder.
curl -X POST 'https://<PROJECT_REF>.supabase.co/storage/v1/object/list/avatars' \
-H "apikey: YOUR_ANON_KEY" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"prefix": "public/",
"limit": 100,
"offset": 0,
"sortBy": {"column": "name", "order": "asc"}
}'
Folder path to list files from.
Maximum number of files to return.
Sort options. Column to sort by: name, created_at, updated_at.
Response
[
{
"name" : "avatar1.png" ,
"id" : "e8c0e3c1-5f3a-4b9e-8f1a-2c3d4e5f6a7b" ,
"updated_at" : "2024-03-04T10:00:00.000Z" ,
"created_at" : "2024-03-04T10:00:00.000Z" ,
"last_accessed_at" : "2024-03-04T10:00:00.000Z" ,
"metadata" : {
"eTag" : " \" abc123 \" " ,
"size" : 52428 ,
"mimetype" : "image/png" ,
"cacheControl" : "max-age=3600"
}
}
]
Search Files
Search for files matching a pattern.
curl -X POST 'https://<PROJECT_REF>.supabase.co/storage/v1/object/list/avatars' \
-H "apikey: YOUR_ANON_KEY" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"prefix": "public/",
"search": "avatar"
}'
Search term to match against file names.
Move File
Move or rename a file.
curl -X POST 'https://<PROJECT_REF>.supabase.co/storage/v1/object/move' \
-H "apikey: YOUR_ANON_KEY" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"bucketId": "avatars",
"sourceKey": "public/avatar1.png",
"destinationKey": "public/avatars/user123.png"
}'
The bucket containing the file.
Current path of the file.
Copy File
Copy a file to a new location.
curl -X POST 'https://<PROJECT_REF>.supabase.co/storage/v1/object/copy' \
-H "apikey: YOUR_ANON_KEY" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"bucketId": "avatars",
"sourceKey": "public/avatar1.png",
"destinationKey": "public/backup/avatar1.png"
}'
Delete Files
Delete one or more files.
curl -X DELETE 'https://<PROJECT_REF>.supabase.co/storage/v1/object/avatars' \
-H "apikey: YOUR_ANON_KEY" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"prefixes": ["public/avatar1.png", "public/avatar2.png"]
}'
Array of file paths to delete.
Public URLs
Get Public URL
For public buckets, files are accessible via a public URL.
https://<PROJECT_REF>.supabase.co/storage/v1/object/public/avatars/public/avatar1.png
No authentication is required for public bucket files.
Signed URLs
Create temporary signed URLs for private files.
curl -X POST 'https://<PROJECT_REF>.supabase.co/storage/v1/object/sign/avatars/private/document.pdf' \
-H "apikey: YOUR_ANON_KEY" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"expiresIn": 3600
}'
Time in seconds until the URL expires (max: 604800 = 7 days).
Response
{
"signedURL" : "https://<PROJECT_REF>.supabase.co/storage/v1/object/sign/avatars/private/document.pdf?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Create Signed Upload URL
Generate a signed URL for uploading files.
curl -X POST 'https://<PROJECT_REF>.supabase.co/storage/v1/object/upload/sign/avatars/private/upload.pdf' \
-H "apikey: YOUR_ANON_KEY" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"expiresIn": 600
}'
Storage Policies
Control access to storage buckets using policies.
Example Policy (SQL)
-- Allow authenticated users to upload to their own folder
CREATE POLICY "Users can upload to own folder"
ON storage . objects
FOR INSERT
WITH CHECK (
bucket_id = 'avatars' AND
auth . uid ():: text = ( storage . foldername ( name ))[1]
);
-- Allow users to read their own files
CREATE POLICY "Users can read own files"
ON storage . objects
FOR SELECT
USING (
bucket_id = 'avatars' AND
auth . uid ():: text = ( storage . foldername ( name ))[1]
);
-- Allow users to delete their own files
CREATE POLICY "Users can delete own files"
ON storage . objects
FOR DELETE
USING (
bucket_id = 'avatars' AND
auth . uid ():: text = ( storage . foldername ( name ))[1]
);
Supabase Storage supports on-the-fly image transformations:
Resize
# Resize to specific dimensions
GET /storage/v1/render/image/authenticated/avatars/avatar.png?width= 300 & height = 300
# Resize with different modes
GET /storage/v1/render/image/authenticated/avatars/avatar.png?width= 300 & height = 300 & resize = cover
GET /storage/v1/render/image/authenticated/avatars/avatar.png?width= 300 & height = 300 & resize = contain
# Convert to WebP
GET /storage/v1/render/image/authenticated/avatars/avatar.png?format=webp
# Convert to AVIF with quality
GET /storage/v1/render/image/authenticated/avatars/avatar.png?format=avif & quality = 80
Quality
# Set quality for lossy formats (1-100)
GET /storage/v1/render/image/authenticated/avatars/avatar.jpg?quality= 75
Best Practices
Use appropriate bucket types
Use public buckets for assets that don’t need authentication
Use private buckets with RLS for user-specific files
Implement file size limits
Set appropriate file size limits on your buckets: { "file_size_limit" : 10485760 } // 10MB
Use image transformations
Transform images on-the-fly to reduce bandwidth and improve performance.
Implement proper RLS policies
Always use Row Level Security policies to control file access: ALTER TABLE storage . objects ENABLE ROW LEVEL SECURITY ;
Use signed URLs for temporary access
Generate short-lived signed URLs for secure temporary access to private files.
Next Steps
Edge Functions Learn about serverless functions
Client Libraries Use Storage with client SDKs