S3 API
Point an S3 SDK at your bucket endpoint and use normal SigV4 requests.
Every bucket has one virtual-hosted endpoint. The bucket name is part of the hostname, which is also why bucket names are globally unique:
https://<bucket>.s3.anything-cloud.com
Use region us-east-1. The SDK endpoint is
https://s3.anything-cloud.com with
virtual-hosted addressing; path-style requests to the bare
endpoint are not routed.
When a custom host is attached, the console shows that host as the primary
endpoint. Use it as the endpoint URL and switch the SDK to path-style
addressing: https://host/<bucket>/<key>. The
generated virtual-host endpoint keeps working, so existing SDK configuration
does not need to change.
Credentials
Open the bucket's Access tab. It shows the access key ID and a masked secret key. Click the secret box to copy it; the value is revealed briefly. These credentials belong to your member account and can access every bucket you own. Treat the secret like a password. Use Refresh key to rotate it; the old key stops working immediately, so update every app that uses it.
Python (boto3)
Install boto3, then create a client with virtual-hosted
addressing and the public endpoint:
import boto3
from botocore.config import Config
s3 = boto3.client(
"s3",
endpoint_url="https://s3.anything-cloud.com",
aws_access_key_id="YOUR_ACCESS_KEY",
aws_secret_access_key="YOUR_SECRET_KEY",
region_name="us-east-1",
config=Config(
signature_version="s3v4",
s3={"addressing_style": "virtual"},
),
)
s3.put_object(Bucket="my-bucket", Key="hello.txt", Body=b"hello")
print(s3.get_object(Bucket="my-bucket", Key="hello.txt")["Body"].read())
boto3 builds https://my-bucket.s3.anything-cloud.com/hello.txt
from that configuration. A plain GET on a public bucket does not
need credentials; everything else does.
AWS CLI
The AWS CLI must use virtual-hosted addressing with this endpoint. Set it once in your profile, then pass the endpoint to each command:
aws configure set default.s3.addressing_style virtual
aws s3 cp ./hello.txt s3://my-bucket/hello.txt \
--endpoint-url https://s3.anything-cloud.com
If your CLI build still sends a path-style request, confirm
default.s3.addressing_style is set to virtual in
the same profile, or use one of the SDK examples above.
Presigned URLs
Sign a URL when a browser or another service needs temporary access without the secret key. With the generated endpoint, the SDK signs the bucket host, so use the same virtual-hosted client:
url = s3.generate_presigned_url(
"get_object",
Params={"Bucket": "my-bucket", "Key": "hello.txt"},
ExpiresIn=300,
)
print(url)
Presigned GETs carry X-Amz-* query parameters and expire at
the time set in the signature. Treat the full URL as the credential: anyone
who has it can read the object until it expires.
Public and private buckets
A public bucket adds an anonymous s3:GetObject policy. Anonymous
reads work, anonymous bucket listings do not, and writes still require a
signature. A private bucket has no anonymous policy; unsigned reads return
403 AccessDenied. Both kinds of bucket use the same endpoint and
the same access keys.
Limits
| Item | Value |
|---|---|
| S3 single PUT | Up to 5 GB |
| Console upload | Up to the configured object limit, currently 100 MB per file |
| Storage | Pay as you go has no cap. Plans include 5, 100, or 250 GB. |
| Object key | Up to 512 characters, no leading slash |
| Listing page | Up to 1,000 keys per S3 page |
The console uses single PUT uploads up to the configured console limit and does not use multipart uploads. The S3 API also has no multipart actions in the member policy, so keep each object at or below 5 GB.
Errors
Responses from the storage gateway use the S3 XML shape, for example:
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied.</Message>
<Resource>/hello.txt</Resource>
</Error>
A missing object returns 404 NoSuchKey. Bucket-level requests
that are not signed, including anonymous listings, return
403 AccessDenied. Failures generated by the edge itself (5xx,
405, 413, and 429) use the edge's own plain response instead of S3 XML.