Skip to content
SuperFiles Docs
Esc
navigateopen⌘Jpreview
On this page

Storage API

REST API reference for uploading, downloading, and managing files.

Storage API

Storage routes use the bucket slug directly as the URL path prefix. There is no /v1/ prefix for storage operations.

Base URL: https://superfiles-api.example.com

Auth: Authorization: Bearer sf_live_<key> on all storage endpoints. Public-bucket reads require no auth.


PUT /{bucket}/{key}

Upload or replace a file. The key supports / separators (e.g. images/2026/photo.jpg). Intermediate virtual folders are created automatically.

curl -X PUT https://superfiles-api.example.com/my-media/images/photo.jpg \
  -H "Authorization: Bearer sf_live_xxxx" \
  -H "Content-Type: image/jpeg" \
  --data-binary @photo.jpg

Response 201:

{
  "key": "images/photo.jpg",
  "bucket": "my-media",
  "size": 123456,
  "etag": "sha256:abc...",
  "contentType": "image/jpeg",
  "format": "jpeg",
  "width": 1920,
  "height": 1080,
  "hasAlpha": false,
  "durationMs": null,
  "createdAt": "2026-01-01T00:00:00Z"
}

GET /{bucket}/{key}

Download a file. Streams the raw blob.

curl https://superfiles-api.example.com/my-media/images/photo.jpg \
  -H "Authorization: Bearer sf_live_xxxx" \
  -o photo.jpg

Optional: ?versionId=<id> to download a specific past version.

Response 200: streaming body with headers:

  • Content-Type, Content-Length, ETag, Last-Modified
  • X-SF-Width, X-SF-Height, X-SF-Format, X-SF-Has-Alpha (media files)

HEAD /{bucket}/{key}

Fetch metadata without downloading the body. Returns the same headers as GET, no body.

Response 200 | 404 { "error": { "code": "object_not_found", "message": "..." } }


DELETE /{bucket}/{key}

Delete a file. Use ?trash=true for a soft delete that can be recovered from the trash.

# Hard delete (permanent)
curl -X DELETE https://superfiles-api.example.com/my-media/images/photo.jpg \
  -H "Authorization: Bearer sf_live_xxxx"

# Soft delete (moves to trash)
curl -X DELETE "https://superfiles-api.example.com/my-media/images/photo.jpg?trash=true" \
  -H "Authorization: Bearer sf_live_xxxx"

Response 204 (no body)


GET /{bucket}

List objects in a bucket with optional prefix filter.

Query params:

Param Type Default Description
prefix string Filter keys starting with this prefix
cursor string Pagination cursor from the previous response
limit int 100 Max objects to return (max: 1000)
curl "https://superfiles-api.example.com/my-media?prefix=images/&limit=20" \
  -H "Authorization: Bearer sf_live_xxxx"

Response 200:

{
  "items": [
    {
      "key": "images/photo.jpg",
      "size": 123456,
      "contentType": "image/jpeg",
      "lastModified": "2026-01-01T00:00:00Z",
      "etag": "sha256:abc...",
      "width": 1920,
      "height": 1080
    }
  ],
  "nextCursor": "images/photo.jpg"
}

POST /{bucket}/{key}?copyFrom={srcKey}

Server-side copy within the same bucket. Returns 201 with the new object metadata.


POST /{bucket}/{key}?moveFrom={srcKey}

Server-side atomic move (copy + delete source). Returns 200 with the new object metadata.


CDN delivery

Public-bucket objects are served via the CDN endpoint with optional on-the-fly transforms. The transform segment is a comma-separated list of directives in alphabetical order.

GET /cdn/{bucket}/{key}               serve original with CDN headers
GET /cdn/{bucket}/{transforms}/{key}  serve transformed variant

Transform examples:

# 800×600 WebP, 85% quality
https://superfiles-api.example.com/cdn/my-media/f_webp,h_600,q_85,w_800/photo.jpg

# Square 300px avatar, auto-format, cover crop
https://superfiles-api.example.com/cdn/my-media/c_cover,f_auto,h_300,w_300/avatar.jpg

# Video thumbnail at 5 seconds
https://superfiles-api.example.com/cdn/my-media/f_jpg,t_5/video.mp4

See Core Concepts → CDN transforms for the full directive reference.

Transformed variants are cached immutably (Cache-Control: public, max-age=31536000, immutable).


S3-compatible endpoint

All storage operations are also available at /s3/{bucket}/{key} with AWS4-HMAC-SHA256 authentication. Use your SuperFiles API key as both the access key ID and the secret key.

export AWS_ACCESS_KEY_ID=sf_live_xxxx
export AWS_SECRET_ACCESS_KEY=sf_live_xxxx
export AWS_ENDPOINT_URL=https://superfiles-api.example.com/s3

aws s3 cp photo.jpg s3://my-media/images/photo.jpg
aws s3 ls s3://my-media/images/

S3 multipart upload (PUT ?partNumber=N&uploadId=X) is supported for files larger than 5 MB, which is what the AWS SDK uses automatically for large files.


Presigned uploads

Generate a short-lived URL that allows a client to upload directly without exposing your API key:

curl -X POST https://superfiles-api.example.com/signed-upload \
  -H "Authorization: Bearer sf_live_xxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "bucket": "my-media",
    "key": "uploads/user-avatar.jpg",
    "contentType": "image/jpeg",
    "expiresIn": 3600
  }'

Response:

{
  "uploadUrl": "https://superfiles-api.example.com/my-media/uploads/user-avatar.jpg?sig=...&expires=...",
  "expiresAt": "2026-01-01T01:00:00Z"
}

The client can then PUT directly to uploadUrl without any Authorization header.

Was this page helpful?