Skip to main content

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"
  }
]
id
string
Unique identifier for the bucket.
name
string
Bucket name.
public
boolean
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"]
  }'
name
string
required
Unique name for the bucket.
public
boolean
default:"false"
Whether the bucket is publicly accessible.
file_size_limit
integer
Maximum file size in bytes (default: 50MB).
allowed_mime_types
array
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'
bucket_name
string
required
The bucket name (in the URL path).
file_path
string
required
The file path within the bucket (in the URL path).
Content-Type
string
required
MIME type of the file.
cache-control
string
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'
x-upsert
boolean
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.

Download with Transformation

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
width
integer
Width in pixels.
height
integer
Height in pixels.
resize
string
Resize mode: cover, contain, fill.
format
string
Output format: webp, jpeg, png, avif.
quality
integer
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"}
  }'
prefix
string
Folder path to list files from.
limit
integer
default:"100"
Maximum number of files to return.
offset
integer
default:"0"
Number of files to skip.
sortBy
object
Sort options.

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"
  }'
bucketId
string
required
The bucket containing the file.
sourceKey
string
required
Current path of the file.
destinationKey
string
required
New path for 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"]
  }'
prefixes
array
required
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
  }'
expiresIn
integer
required
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]
  );

Image Transformations

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

Format Conversion

# 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 public buckets for assets that don’t need authentication
  • Use private buckets with RLS for user-specific files
Set appropriate file size limits on your buckets:
{"file_size_limit": 10485760} // 10MB
Transform images on-the-fly to reduce bandwidth and improve performance.
Always use Row Level Security policies to control file access:
ALTER TABLE storage.objects ENABLE ROW LEVEL SECURITY;
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

Build docs developers (and LLMs) love