Skip to content

S3-compatible API

Connect rclone, restic, Cyberduck, the AWS CLI, boto3, and NAS backup apps to SteadyLink buckets with app keys and AWS Signature Version 4.

On this page

SteadyLink buckets speak the Amazon S3 protocol, so tools built for S3 can sync, back up, and browse them. Use this page to create an app key, configure your tool, and understand where SteadyLink behaves differently from Amazon S3.

Files written through S3 follow the same rules as dashboard uploads: plan upload limits, storage quota, malware scanning, workspace encryption, and audit logs. A PUT to a key that already exists adds a new revision behind the same stable link, so you can sync a folder with rclone and every published https://cdn.steadylink.io/a/{asset_id} link keeps serving the latest file.

Connection details#

SettingValue
Endpointhttps://api.steadylink.io/s3 (path style)
Dedicated hosthttps://s3.steadylink.io, for tools that only accept a bare host (restic, Cyberduck, many NAS apps)
Regionauto. Any region name is accepted; it only has to match what the client signs with.
AddressingPath style: https://api.steadylink.io/s3/{bucket}/{key}. Virtual-host style ({bucket}.s3.steadylink.io) works only on the dedicated host.
SignatureAWS Signature Version 4, in the Authorization header or as presigned query parameters. Version 2 is not supported.
Bucket nameThe bucket's slug, or its ID when it has no S3-compatible slug. rclone lsd or aws s3 ls shows the names.
KeyThe file path inside the bucket, for example photos/2024/beach.jpg.

App keys#

S3 tools authenticate with an app key: an access key ID that starts with SL and a 40-character secret. App keys are separate from workspace API keys.

  • An app key belongs to one user in one workspace and acts with that user's role. Removing the user from the workspace, or lowering their role, takes effect on the next request.
  • Each user can have up to 20 active app keys per workspace.
  • The secret is shown only in the response that creates the key. Store it right away.
  • App keys bypass workspace SSO enforcement, in the same way workspace API keys do. Revoke a person's keys when they leave.

Create an app key#

POST/api/s3-keys
Signed-in user session

App keys are currently created through the API, with a signed-in user's session token (Authorization: Bearer). Workspace API keys cannot create them, because an app key acts as a person; a request with X-API-Key returns 403. A dashboard screen for app keys is coming. Send X-Workspace-Id if you belong to more than one workspace.

Body

namestringRequired
A label, 1 to 200 characters, for example NAS backup.
readOnlybooleanDefault false
The key can list and download, but every write returns AccessDenied. Viewers can create read-only keys; a read-write key needs a role that can write files.
bucketIduuid
Limit the key to one bucket. ListBuckets then returns only that bucket, and the key cannot create or delete buckets. An unknown bucket returns 404.
curl
curl -X POST https://api.steadylink.io/api/s3-keys \
  -H "Authorization: Bearer $STEADYLINK_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "NAS backup", "readOnly": false, "bucketId": "8b1f6c2e-4a7d-4f0e-b3c9-2d5e7a9f1c04"}'
201 CreatedResponse
{
  "id": "5c2e9a1f-3b7d-4e8a-9f0c-1d2b3a4c5e6f",
  "name": "NAS backup",
  "accessKeyId": "SLQ4M7ZK2XB5N3TJ6WRA",
  "readOnly": false,
  "bucketId": "8b1f6c2e-4a7d-4f0e-b3c9-2d5e7a9f1c04",
  "createdAt": "2026-10-08T09:30:12.418211",
  "lastUsedAt": null,
  "revokedAt": null,
  "secretAccessKey": "q7Xb2LwP9sKd4RmT1vYc8NfJ3hZa6GeU5oWi0BtE",
  "endpoint": "https://api.steadylink.io/s3",
  "region": "auto",
  "forcePathStyle": true
}

Creating a twenty-first active key returns 409 with the code s3_key_limit_reached.

List your app keys#

GET/api/s3-keys
Signed-in user session

Returns your active keys in the current workspace, newest first, as { "items": [...], "endpoint", "region", "forcePathStyle" }. Each item has the same fields as the create response without secretAccessKey. lastUsedAt is updated at most every five minutes.

Revoke an app key#

DELETE/api/s3-keys/{key_id}
Signed-in user session

Returns { "revoked": true }. You can revoke your own keys; workspace admins can revoke anyone's, for offboarding. Revoking an already revoked key also returns { "revoked": true }. Creation and revocation are recorded in the audit log as workspace.s3_key_create and workspace.s3_key_revoke.

Set up your tool#

The examples use the access key ID SLXXXXXXXXXXXXXXXXXX, the secret YOUR_SECRET, and a bucket named my-bucket.

To install rclone and create this remote in one step, see Connect rclone in one command.

Create the remote from the command line:

Terminal
rclone config create steadylink s3 \
  provider=Other \
  access_key_id=SLXXXXXXXXXXXXXXXXXX \
  secret_access_key=YOUR_SECRET \
  endpoint=https://api.steadylink.io/s3 \
  region=auto \
  force_path_style=true

Or add it to rclone.conf:

rclone.conf
[steadylink]
type = s3
provider = Other
access_key_id = SLXXXXXXXXXXXXXXXXXX
secret_access_key = YOUR_SECRET
endpoint = https://api.steadylink.io/s3
region = auto
force_path_style = true

Then:

Terminal
rclone lsd steadylink:                                   # list buckets
rclone copy ~/Pictures steadylink:my-bucket/pictures
rclone sync ~/Documents steadylink:my-bucket/documents
rclone check ~/Documents steadylink:my-bucket/documents

rclone stores modification times in X-Amz-Meta-Mtime and, for multipart uploads, the MD5 in X-Amz-Meta-Md5chksum. Both are kept with each revision, so sync and check work without re-uploading. Changing only a modification time (rclone touch, or a sync where only the time differs) updates the current revision's metadata and does not create a new revision.

Keep the chunk size at 5 MiB or more; rclone's default is fine.

NAS backup apps usually ask for a server address rather than a URL: enter s3.steadylink.io, choose a custom S3-compatible provider, and keep HTTPS on.

Supported operations#

OperationNotes
ListBuckets, HeadBucket, GetBucketLocationThe location is empty, so clients fall back to their configured region.
CreateBucketCreates a bucket whose slug is the S3 name. Names are global and must be 3 to 63 lowercase letters, digits, dots, or hyphens. A taken name returns BucketAlreadyExists.
DeleteBucketOnly when the bucket is empty (BucketNotEmpty otherwise).
ListObjects (v1) and ListObjectsV2prefix, delimiter (CommonPrefixes for folders), max-keys, marker, start-after, continuation tokens, and encoding-type=url.
HeadObject, GetObjectA single Range, If-Match, If-None-Match, If-Modified-Since, If-Unmodified-Since, response-* overrides, and presigned URLs.
PutObjectStreaming, Content-MD5 and x-amz-content-sha256 checks, aws-chunked uploads (signed chunks and checksum trailers), and x-amz-meta-* metadata up to 2 KB in total.
CopyObjectServer-side, with x-amz-metadata-directive COPY or REPLACE. Clients use it for renames.
DeleteObject, DeleteObjectsDeleting a key removes the file and all of its revisions, as in the dashboard. Its stable link stops working.
Multipart uploadCreateMultipartUpload, UploadPart, ListParts, CompleteMultipartUpload, AbortMultipartUpload, and ListMultipartUploads.
GetObjectAcl, PutObjectAcl, GetBucketAclAccepted for client compatibility, but they change nothing. Access is controlled by app keys only.

ETags#

The ETag is the MD5 of the whole file, including for multipart uploads, where Amazon S3 would return an {md5-of-parts}-{N} value instead. Tools that compare ETags to local MD5 sums therefore work for every file.

Revisions created before the S3 API existed have an ETag ending in -1, which tells clients that it is not an MD5. Tools then fall back to size and modification time, or to the X-Amz-Meta-Md5chksum value rclone stores.

Errors#

Errors use the standard S3 XML body, with codes such as NoSuchKey, NoSuchBucket, AccessDenied, SignatureDoesNotMatch, InvalidRange, and EntityTooLarge. Error responses carry an x-amz-request-id header and the same ID in RequestId.

Text
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>QuotaExceeded</Code><Message>...</Message><Resource>/s3/my-bucket/video.mp4</Resource><RequestId>7d3c1f2e-...</RequestId></Error>

Two cases are specific to SteadyLink:

CodeHTTPMeaning
QuotaExceeded403The workspace's storage or delivery allowance is used up. It is a 403 so clients fail fast instead of retrying. Free space or upgrade, then run the job again.
AccessDenied with a message starting Upload blocked403Malware was found in the file (Upload blocked: malware detected), or the bucket's file-type or size policy rejected it (Upload blocked by bucket policy). Retrying the same file will fail again.

A read-only key that tries to write, or a bucket-limited key that touches another bucket, also gets AccessDenied.

Limits and rate limits#

  • The largest object is the plan's maximum upload size, and storage counts against the plan quota. See Usage and limits.
  • Multipart parts are limited to 5 GiB each. Every part except the last must be at least 5 MiB and all parts except the last must be the same size; rclone and the AWS tools already do this.
  • Downloads count against the workspace delivery allowance, like /a links.
  • Each app key can make 1,200 reads and 600 writes per minute. Requests over the limit get SlowDown (HTTP 503), which S3 clients retry with backoff. Failed signature checks are limited per client IP address.

Known limitations#

  • No versioning API. versionId and ListObjectVersions are not supported. Revisions exist and are visible in the dashboard and the revisions API, but S3 always reads and writes the current one.
  • No bucket policies, CORS, lifecycle rules, tagging, object lock, or SSE-C. ACL calls are accepted and ignored.
  • No UploadPartCopy or GetObject?partNumber.
  • Large files in memory. Committing a file reads it into memory on the API server, as dashboard commits do. In workspaces with encryption, a Range request decrypts the whole object first, so reading parts of very large files is slow.
  • Malware scanning timing. With synchronous scanning an infected upload is rejected. With asynchronous scanning the upload succeeds and the object later becomes unreadable (AccessDenied) if the scan finds malware. Objects still waiting for a scan can be read with an app key.
  • Key rules. Keys cannot start with / or contain //, . or .. segments, or control characters. Folder paths and file names are limited to 512 characters each (KeyTooLongError).
  • Content checks. A file whose bytes clearly contradict its declared Content-Type is rejected, as in the dashboard.
  • Abandoned multipart uploads expire after 7 days.
  • Empty folders. Folders created in the dashboard appear in listings only while they have a folder marker. rclone does not create empty folders on S3 remotes.

Next steps#