What you need:
- You created a bucket. Use its name in place of
{bucket}
below.
- You created a RLS policy for table
storage.objects
that allows INSERT for authenticated users.
- You have the reference ID of your project at hand. When hosting on supabase.com, that is the subdomain part of the URLs used for all your API requests. Use it in place of
{ref}
below.
- You have the anon role API key for your project. Use it instead of
{anon-key}
below.
- You have a currently valid JWT token for your user. Use it in place of
{bearer-auth-token}
below.
- You have a file you want to upload, with an absolute path like
/path/to/file.ext
. Use that absolute path in place of {path-and-filename.ext}
below, and use the filename and extension in place of {filename.ext}
below.
Now, a working upload command would look like this:
curl \
-X POST "https://{ref}.supabase.co/storage/v1/object/{bucket}/{filename.ext}" \
--data-binary "@{path-and-filename.ext}" \
-H "apikey: {anon-key}" \
-H "Authorization: Bearer {bearer-auth-token}"
Notes:
The URL path must be prefixed with storage/v1/
. This is the part I had to test / reverse engineer. The manual still mentions apiv0/
, which is outdated, and also misses to mention the storage/
prefix. The Swagger UI docs mentions neither storage/
nor v1/
, but both are required.
In the request URL https://{ref}.supabase.co/storage/v1/object/{bucket}/{filename.ext}
you can actually set {filename.ext}
to any filename with extension that you want to use to save the file server-side. It does not have to be the same as the file's local filename. You can even include any path you like.
On success, the result will be a JSON object {"Key": "{bucket}/{filename.ext}"}
with the values you used in the request URL. This is the key to identify the uploaded file server-side when you want to download, move it etc..
Since path and filename serve as the key to identify the file, trying to upload a file with the same path and filename into the same bucket will result in an error {"statusCode": "409", "error": "Duplicate", "message": "The resource already exists"}
.