Skip to main content

S3 API overview

STRG speaks the Amazon S3 REST API, so the tools you may already know - the AWS CLI, the AWS SDKs and other S3 clients - work with your buckets as they are. All they need is a STRG endpoint and a STRG access key to sign with. This is the API for an application storing its uploads, a nightly backup job, or an agent keeping its files in a bucket.

This page gathers what every operation has in common: where to send requests, how to sign them, and the handful of places where STRG behaves differently from Amazon S3. Each operation has a page of its own, listed under Supported operations.

Regions and endpoints​

Every bucket lives in one region, picked when the bucket is created. Each region has its own endpoint, and an endpoint answers for the buckets in its own region.

RegionNameEndpoint (path-style)Virtual-hosted form
us-east-1US Easthttps://s3.us-east-1.strg.comhttps://<bucket>.s3.us-east-1.strg.com
eu-central-1EU Centralhttps://s3.eu-central-1.strg.comhttps://<bucket>.s3.eu-central-1.strg.com

A client is configured with both the endpoint and its matching region, because the region is part of the signature. A request signed for a region other than the endpoint's answers 400 AuthorizationHeaderMalformed (400 AuthorizationQueryParametersError for a presigned URL), and the error message names the region the endpoint expects.

Addressing​

S3 has two ways of naming a bucket in a URL, and STRG understands both.

StyleRequest for photos/2024/cat.jpg in my-bucket
Path-stylehttps://s3.eu-central-1.strg.com/my-bucket/photos/2024/cat.jpg
Virtual-hostedhttps://my-bucket.s3.eu-central-1.strg.com/photos/2024/cat.jpg
Bucket names with a dot

A bucket name containing a dot (my.bucket) works with path-style addressing. In virtual-hosted form the TLS handshake fails before the request is even sent. For such a bucket, the client setting is forcePathStyle: true (JavaScript), addressing_style: "path" (boto3) or s3.addressing_style = path (AWS CLI).

Client configuration​

The AWS CLI and the SDKs read your credentials from the environment: AWS_ACCESS_KEY_ID holds your access key's ID and AWS_SECRET_ACCESS_KEY its secret. Each example below lists the objects in my-bucket in eu-central-1, once per addressing style.

Path-style​

aws configure set default.s3.addressing_style path

aws s3api list-objects-v2 \
--bucket my-bucket \
--endpoint-url https://s3.eu-central-1.strg.com \
--region eu-central-1

Virtual-hosted​

aws configure set default.s3.addressing_style virtual

aws s3api list-objects-v2 \
--bucket my-bucket \
--endpoint-url https://s3.eu-central-1.strg.com \
--region eu-central-1

The SDKs' defaults - request checksums and aws-chunked streaming uploads included - work as they are, with nothing to switch off.

Authentication​

Every signed request uses AWS Signature Version 4 (AWS4-HMAC-SHA256), with an access key created on the Access Keys page of the dashboard, through the MCP server or through the REST API. Access keys describes the permissions a key can carry.

The table shows each way of signing and how STRG handles it.

Header signingThe Authorization header
Presigned URLsQuery-string signing, X-Amz-Expires from 1 second to 7 days (604,800 seconds)
Streaming uploadsaws-chunked bodies (STREAMING-AWS4-HMAC-SHA256-PAYLOAD, STREAMING-AWS4-HMAC-SHA256-PAYLOAD-TRAILER, STREAMING-UNSIGNED-PAYLOAD-TRAILER) on PutObject and UploadPart, with every chunk verified. Trailing checksums: CRC32, CRC32C, CRC64NVME, SHA-1 and SHA-256. A presigned URL carries its body in one piece instead: aws-chunked in a presigned URL answers 400 InvalidRequest
UNSIGNED-PAYLOADAccepted
Clock skewUp to 15 minutes between X-Amz-Date and the server's clock; beyond that, 403 RequestTimeTooSkewed
x-amz-* headersEvery one is part of the signature. A request carrying an unsigned x-amz-* header answers 403 AccessDenied
Unsigned (anonymous) requestsWelcome for GetObject and HeadObject on a bucket whose Bucket Protection is off - Anonymous reads has the details. Every other unsigned request, listing included, answers 403 AccessDenied

STRG keeps to Signature Version 4 and long-lived access keys, so a few other mechanisms get a clear answer instead:

MechanismAnswer
Signature Version 2 (AWS AKID:signature)400 InvalidRequest
SigV4A (AWS4-ECDSA-P256-SHA256)400 InvalidRequest
Session tokens (x-amz-security-token, X-Amz-Security-Token) and S3 Express sessions (x-amz-s3session-token)400 InvalidToken - STRG has no temporary credentials, so there is no token to send
Browser POST uploads with a policy document501 NotImplemented

A revoked access key, or a change to the account behind one, takes effect within 60 seconds.

Anonymous reads​

A bucket whose Bucket Protection is off is public: anyone can read its objects without signing, which suits a website's images or files meant to be shared by link. The read goes to the bucket's own regional endpoint, path-style or virtual-hosted:

curl https://my-bucket.s3.eu-central-1.strg.com/photos/2024/cat.jpg

Here is how each kind of anonymous request is answered:

RequestAnswer
GET or HEAD of an object in a public bucketThe object, as for a signed request. Range, versionId and conditional headers work
Listing a public bucket, or any other operation403 AccessDenied
A response-* query parameter (response-content-type, ...)400 InvalidRequest, as on Amazon S3
A bucket with Bucket Protection on403 AccessDenied
A bucket that does not exist, or is in another region404 NoSuchBucket

A bucket created a moment ago can answer 404 NoSuchBucket to anonymous requests for a few seconds, until every endpoint has heard about it.

Anonymous reads can be answered from a cache, which makes popular public files quick to fetch. That happens for an object stored with a Cache-Control that lets a shared cache keep it (public, max-age=60, for example); an object without one is never cached. A cached answer is kept for its max-age (or s-maxage) or 5 minutes, whichever is shorter, and the reader is still sent the object's own Cache-Control. The cache is never cleared early, so for up to 5 minutes after an object is overwritten or deleted, Bucket Protection is turned on, or the bucket's CORS rules change, anonymous readers can still get the previous answer. Signed requests never use the cache.

CORS​

A browser asks permission with a CORS preflight (OPTIONS) before a web page talks to your bucket directly. STRG answers it on the bucket's regional endpoint from the bucket's CORS rules, as Amazon S3 does, and a preflight the rules do not allow answers 403 AccessForbidden.

403 AccountProblem​

CreateBucket answers 403 AccountProblem while your account has no verified card on file: a card comes before the first bucket, and Billing in the dashboard, https://app.strg.com/billing, is where it is added. A card is required explains why. Once the card is there, the same request succeeds.

Differences from Amazon S3​

STRG behaves like Amazon S3 almost everywhere. Where it differs, it is usually because there is less to configure - and the table lists each place, so nothing comes as a surprise.

AreaAmazon S3STRG
Bucket in another region301 with x-amz-bucket-region, which the SDKs follow404 NoSuchBucket. Each endpoint answers for its own region, and the SDKs do not retry, so a client set to another region hears that a bucket does not exist even while the dashboard shows it. Setting the client to the bucket's region is all it takes
Nothing stored in the endpoint's region yetAny valid key reaches the endpointThe plain truth: 404 NoSuchBucket for a bucket operation, an empty ListBuckets result, and 501 NotImplemented for an operation STRG does not offer. CreateBucket creates the bucket
A key created moments agoWorks at onceIn a region where you already store data, a brand-new key can take a moment to arrive: until it does, every operation but CreateBucket answers 403 InvalidAccessKeyId, and a retry shortly afterwards succeeds
CreateBucketCreates in any regionCreates the bucket in the endpoint's region - any region, your first bucket there included. A LocationConstraint naming another region answers 400 InvalidLocationConstraint. A first bucket also sets up storage in the region, which takes a little longer - up to about 90 seconds - and from then on the key that signed the request works in that region too. A creation still running at that point answers 503 SlowDown with Retry-After; the SDKs retry automatically, and the retry joins the same creation rather than starting another
Object Lock at creationx-amz-bucket-object-lock-enabled: true on CreateBucketTwo steps: the bucket is created, then PutObjectLockConfiguration enables Object Lock. x-amz-bucket-object-lock-enabled: true on CreateBucket answers 501 NotImplemented
Deleting and re-creating a bucketA policy naming the bucket keeps applyingA bucket re-created under a deleted bucket's name is a new bucket, so an access key limited to the old one does not reach it. A new key for the new bucket takes only a moment to create
Bucket names3-63 characters3-58 characters, with the same rules otherwise. Names are globally unique across STRG
GetBucketLocationThe regionThe STRG region label, and an empty LocationConstraint for us-east-1, as S3 answers it
ListBucketsEvery bucketThe buckets in the endpoint's region, all in one answer - it is never paginated - and without BucketRegion. A key limited to specific buckets lists them when it holds the List all bucket names permission; without it, ListBuckets answers 403 AccessDenied
HeadBucket403 for a bucket you cannot access404 for a bucket that is not yours, exactly as for one that does not exist
Multipart parts5 MiB to 5 GiB, 1-10,000 parts5,000,000 bytes (except the last part) to 5 GiB, part numbers 1-10,000
Incomplete multipart uploadsBilledBilled as stored data until completed or aborted. A lifecycle policy can abort them for you
VersioningOff until enabled; can be suspendedAlways on, so an earlier version is always there to go back to. A delete writes a delete marker, and every version is billed as stored data until it is deleted or a lifecycle policy removes it. PutBucketVersioning with Suspended answers 501 NotImplemented
Storage classesSeveralSTANDARD, for every object - nothing to choose between
EncryptionSSE-S3, SSE-KMS, SSE-CServer-side encryption with STRG-managed keys (AES256) as a bucket default, and SSE-C per request. SSE-KMS answers 501 NotImplemented. GetBucketEncryption answers AES256 even for a bucket never given a default
ACLsGrants and canned ACLsOne canned ACL per bucket, private or public-read. An object shares its bucket's ACL, so PutObjectAcl succeeds when it names the bucket's own and answers 501 NotImplemented otherwise. Grant headers and XML grant bodies answer 501 NotImplemented
TaggingObject and bucket tagsNo tags: object and bucket tag sets are always empty, so tools that read them still work, and x-amz-tagging on an upload or copy answers 501 NotImplemented
Conditional writesIf-None-Match / If-Match on PutObject, CompleteMultipartUpload and CopyObject501 NotImplemented, so a client knows straight away
Bucket policies, public access block, ownership controls, notifications, accelerationConfigurableNothing to configure. The read operations answer as AWS does for a bucket never configured, so tools that probe them work as usual
x-amz-expected-bucket-owner, x-amz-source-expected-bucket-ownerCheckedWelcome, with nothing to check: a key only ever reaches buckets of its own account
Object keys with . or .. path segmentsStored and read as sentA key with a . or .. segment (a/../b, a/./b), percent-encoded as %2e or not, cannot travel safely in a URL: the request answers 400 InvalidURI, and nothing is stored or read under any name. DeleteObjects, which carries the key in the request body, removes an existing one
Keys limited to a prefix-A listing passes the key's prefix as prefix (or a longer one); any other listing answers 403 AccessDenied
Streaming a body without a lengthAllowed in some casesTransfer-Encoding: chunked without Content-Length answers 411 MissingContentLength. aws-chunked uploads work as usual
Throttling503 SlowDown503 SlowDown with Retry-After, which the SDKs retry automatically

Each operation's page has the differences particular to it.

Supported operations​

Buckets​

Operation
ListBucketsLists the buckets in the endpoint's region
HeadBucketTells whether a bucket exists and you can reach it
GetBucketLocationAnswers a bucket's region
CreateBucketCreates a bucket in the endpoint's region
DeleteBucketDeletes an empty bucket

Bucket configuration​

Operation
GetBucketAcl, PutBucketAclprivate or public-read
GetBucketCors, PutBucketCors, DeleteBucketCorsCORS rules
GetBucketLifecycleConfiguration, PutBucketLifecycleConfiguration, DeleteBucketLifecycleLifecycle policies
GetBucketLifecycle, PutBucketLifecycleThe older, deprecated forms of the above, still answered
GetBucketEncryption, PutBucketEncryptionDefault encryption, AES256
GetBucketVersioning, PutBucketVersioningAlways Enabled
GetBucketTagging, DeleteBucketTaggingEmpty tag sets, for tools that read them
GetBucketAccelerateConfiguration, GetBucketNotification, GetBucketNotificationConfiguration, GetBucketOwnershipControls, GetBucketPolicy, GetBucketRequestPayment, GetPublicAccessBlockThe never-configured answer, for tools that probe them

Objects​

Operation
PutObjectUploads an object of up to 5 GiB
GetObject, HeadObjectReads an object, or its metadata
CopyObjectCopies an object
DeleteObject, DeleteObjectsWrite delete markers, or delete versions permanently
ListObjectsV2, ListObjects, ListObjectVersionsList objects, or every version and delete marker
GetObjectAcl, PutObjectAclThe bucket's ACL
GetObjectTagging, DeleteObjectTaggingEmpty tag sets, for tools that read them

Multipart uploads​

Multipart uploads carry a large object in parts, each retried on its own if a connection drops.

Operation
CreateMultipartUploadStarts an upload
UploadPart, UploadPartCopyUploads a part, or copies one from an existing object
CompleteMultipartUpload, AbortMultipartUploadFinish or discard an upload
ListParts, ListMultipartUploadsShow the uploads in progress and their parts

Object Lock​

Operation
GetObjectLockConfiguration, PutObjectLockConfigurationA bucket's Object Lock setting and default retention
GetObjectRetention, PutObjectRetentionAn object version's retention
GetObjectLegalHold, PutObjectLegalHoldAn object version's legal hold
Object Lock is permanent

Enabling Object Lock on a bucket is permanent: it can never be switched off again. Locked object versions stay billed as stored data until their lock expires. Object Lock explains both before a PutObjectLockConfiguration call makes them true for a bucket.

Other S3 operations​

The rest of the S3 API answers 501 NotImplemented, so a client knows straight away - as does a request with a query parameter none of the operations above accepts:

CreateBucketMetadataConfiguration, CreateBucketMetadataTableConfiguration, CreateSession, DeleteBucketAnalyticsConfiguration, DeleteBucketEncryption, DeleteBucketIntelligentTieringConfiguration, DeleteBucketInventoryConfiguration, DeleteBucketMetadataConfiguration, DeleteBucketMetadataTableConfiguration, DeleteBucketMetricsConfiguration, DeleteBucketOwnershipControls, DeleteBucketPolicy, DeleteBucketReplication, DeleteBucketWebsite, DeleteObjectAnnotation, DeletePublicAccessBlock, GetBucketAbac, GetBucketAnalyticsConfiguration, GetBucketIntelligentTieringConfiguration, GetBucketInventoryConfiguration, GetBucketLogging, GetBucketMetadataConfiguration, GetBucketMetadataTableConfiguration, GetBucketMetricsConfiguration, GetBucketPolicyStatus, GetBucketReplication, GetBucketWebsite, GetObjectAnnotation, GetObjectAttributes, GetObjectTorrent, ListBucketAnalyticsConfigurations, ListBucketIntelligentTieringConfigurations, ListBucketInventoryConfigurations, ListBucketMetricsConfigurations, ListDirectoryBuckets, ListObjectAnnotations, PutBucketAbac, PutBucketAccelerateConfiguration, PutBucketAnalyticsConfiguration, PutBucketIntelligentTieringConfiguration, PutBucketInventoryConfiguration, PutBucketLogging, PutBucketMetricsConfiguration, PutBucketNotification, PutBucketNotificationConfiguration, PutBucketOwnershipControls, PutBucketPolicy, PutBucketReplication, PutBucketRequestPayment, PutBucketTagging, PutBucketWebsite, PutObjectAnnotation, PutObjectTagging, PutPublicAccessBlock, RenameObject, RestoreObject, SelectObjectContent, UpdateBucketMetadataAnnotationTableConfiguration, UpdateBucketMetadataInventoryTableConfiguration, UpdateBucketMetadataJournalTableConfiguration, UpdateObjectEncryption, WriteGetObjectResponse.

View as Markdown