Skip to content

Buckets

List, create, read, configure, and delete buckets, the top-level containers that hold a workspace's folders and files.

On this page

A bucket is a top-level container in a workspace, such as Marketing or Product media. Folders and files live inside it, and its settings decide the default visibility of new files and which uploads it accepts. Use these endpoints to find a bucket ID for uploads, create buckets from a provisioning script, apply an upload policy, or tear a bucket down.

Bucket routes live under /api/assets for historical reasons: in the API, a bucket is an asset of kind bucket, and a file is an asset of kind object. Bucket IDs and file asset IDs are both UUIDs, so keep track of which one you hold.

The JavaScript examples assume const steadylink = new SteadyLink({ apiKey: process.env.STEADYLINK_API_KEY! }) and the Python examples assume client = SteadyLink(api_key=os.environ["STEADYLINK_API_KEY"]).

Endpoints#

OperationMethod and pathScope
List bucketsGET /api/assets/assets:read
Create a bucketPOST /api/assets/assets:write
Get a bucketGET /api/assets/{bucket_id}assets:read
Set a bucket's default privacyPOST /api/assets/{bucket_id}/privacyassets:write
Update bucket settingsPOST /api/assets/{bucket_id}/settingsassets:write
Delete a bucketDELETE /api/assets/{bucket_id}assets:write

Operations#

List buckets#

GET/api/assets/
Requiresassets:read

Returns the workspace's buckets, newest first.

Query parameters

limitintegerDefault 20
Number of buckets per page. Values outside 1 to 100 are clamped into that range.
cursorstring
The nextCursor from the previous page. It is the createdAt of the last bucket returned. A value that is not a timestamp is ignored and the first page is returned.
curl "https://api.steadylink.io/api/assets/?limit=100" \
  -H "X-API-Key: $STEADYLINK_API_KEY"
200 OKResponse
{
  "items": [
    {
      "id": "7c1e4b2a-5d3f-4e8a-9b61-2f0c8d4a7e15",
      "name": "Marketing",
      "slug": "marketing",
      "kind": "bucket",
      "createdAt": "2026-08-17T18:31:00.412093",
      "isPrivate": false
    },
    {
      "id": "c2a7f0e9-3b14-4d86-8e5a-0f9d1b3c7a42",
      "name": "Product media",
      "slug": null,
      "kind": "bucket",
      "createdAt": "2026-07-02T09:12:45.003118",
      "isPrivate": true
    }
  ],
  "nextCursor": "2026-07-02T09:12:45.003118"
}

Response fields

items[].iduuid
Bucket ID. Use it as bucketId when you create uploads.
items[].namestring
Display name.
items[].slugstring | null
Optional short identifier. The CLI and findBucket() accept it in place of the ID.
items[].isPrivateboolean
The bucket's default privacy. It decides delivery only for files whose visibility is inherit.
nextCursorstring | null
Pass as cursor for the next page. It is set on every non-empty page, including the last one.

nextCursor alone does not tell you that more pages exist. Stop when a page returns fewer buckets than limit, or none.

Create a bucket#

POST/api/assets/
Requiresassets:write

Body

namestringRequired
Display name, for example Product media.
slugstring
Optional short identifier, up to 300 characters, for example product-media. Slugs are unique across all of SteadyLink, not only your workspace.
curl -X POST "https://api.steadylink.io/api/assets/" \
  -H "X-API-Key: $STEADYLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Product media", "slug": "acme-product-media" }'
201 CreatedResponse
{ "id": "c2a7f0e9-3b14-4d86-8e5a-0f9d1b3c7a42" }

A new bucket starts private or public according to the workspace's default visibility. Workspaces without a stored default start new buckets private, so nothing is published by accident. Change it afterwards with Set a bucket's default privacy or Update bucket settings.

Get a bucket#

GET/api/assets/{bucket_id}
Requiresassets:read

Returns the bucket with its settings. A bucket in another workspace returns 403; an unknown ID returns 404 Asset not found.

curl "https://api.steadylink.io/api/assets/7c1e4b2a-5d3f-4e8a-9b61-2f0c8d4a7e15" \
  -H "X-API-Key: $STEADYLINK_API_KEY"
200 OKResponse
{
  "id": "7c1e4b2a-5d3f-4e8a-9b61-2f0c8d4a7e15",
  "name": "Marketing",
  "slug": "marketing",
  "createdAt": "2026-08-17T18:31:00.412093",
  "isPrivate": false,
  "settings": {
    "default_public": true,
    "max_upload_mb": 50,
    "allowed_mime_prefixes": ["image/", "application/pdf"]
  }
}

settings is null until a setting has been saved. Its keys are described under Update bucket settings.

Set a bucket's default privacy#

POST/api/assets/{bucket_id}/privacy
Requiresassets:write

Query parameters

is_privatebooleanRequired
true makes the bucket private, false makes it public.
curl
curl -X POST "https://api.steadylink.io/api/assets/7c1e4b2a-5d3f-4e8a-9b61-2f0c8d4a7e15/privacy?is_private=true" \
  -H "X-API-Key: $STEADYLINK_API_KEY"
200 OKResponse
{ "id": "7c1e4b2a-5d3f-4e8a-9b61-2f0c8d4a7e15", "is_private": true }

This changes the bucket's own privacy flag, which governs delivery only for files whose visibility is inherit. Files uploaded through the API and dashboard receive an explicit public or private visibility when they are created, so flipping this flag does not change them. To make every file in a bucket private, set each file's visibility with Set file visibility. To change what new uploads get, set default_public in the bucket settings.

Update bucket settings#

POST/api/assets/{bucket_id}/settings
Requiresassets:write

Send a JSON object with the settings to change. Settings you omit keep their current values, and keys not listed below are dropped. Setting keys are snake_case.

Body

default_publicboolean
Visibility given to new files in this bucket: true for public, false for private. Without it, new files follow the workspace default.
max_upload_mbinteger
Largest file this bucket accepts, in MiB. It can only tighten the plan's upload limit, never raise it.
allowed_mime_prefixesstring[]
Accept only files whose detected type starts with one of these prefixes, for example ["image/", "application/pdf"]. Send [] to allow all types.
allowed_extensionsstring[]
Accept only these filename extensions, with or without the leading dot, for example ["webp", ".pdf"]. Send [] to allow all.
block_mime_mismatchbooleanDefault true
Reject an upload when the content type stored with its bytes and the type detected from the bytes are both concrete and belong to different families, for example image/png bytes that are actually a ZIP archive. Bytes sent to a presigned upload URL are always stored as application/octet-stream, which never conflicts, so this check mainly affects other upload paths.
html_download_onlyboolean
Serve HTML files as downloads (Content-Disposition: attachment) instead of rendering them. Downloads are the default.
svg_download_onlyboolean
Serve SVG files as downloads instead of rendering them inline. Downloads are the default.
pdf_sanitize_enabledboolean
Serve a sanitized copy of PDFs with active content removed.
curl -X POST "https://api.steadylink.io/api/assets/7c1e4b2a-5d3f-4e8a-9b61-2f0c8d4a7e15/settings" \
  -H "X-API-Key: $STEADYLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "default_public": true,
    "max_upload_mb": 50,
    "allowed_mime_prefixes": ["image/", "application/pdf"]
  }'
200 OKResponse
{
  "updated": true,
  "settings": {
    "default_public": true,
    "max_upload_mb": 50,
    "allowed_mime_prefixes": ["image/", "application/pdf"]
  }
}

Upload policies are checked when an upload is finalized, after the bytes have been sent. A file that breaks the policy ends in the blocked state with the error code policy and a message such as File type not allowed by bucket policy. Check types and sizes before uploading if you want to fail faster. See Uploads.

Delete a bucket#

DELETE/api/assets/{bucket_id}
Requiresassets:write

Deletes the bucket, every file in it, every retained revision, cached image variants, and folder markers. Storage used by those revisions is released from the workspace's usage. Every stable link to a file in the bucket stops working.

curl -X DELETE "https://api.steadylink.io/api/assets/c2a7f0e9-3b14-4d86-8e5a-0f9d1b3c7a42" \
  -H "X-API-Key: $STEADYLINK_API_KEY"
200 OKResponse
{ "deleted": true }

Passing a file's asset ID instead of a bucket ID returns 404 Bucket not found. To delete one file, use Delete a file.

Next steps#