# Contact us (/contact) Tell us what you're working on and we'll reply by email, usually within two working days. For quick questions, the [Discord](https://discord.gg/shelbyserves) is often faster. # Account & access (/protocol/account-and-access) ## Projects, buckets and access keys * **Projects** group your buckets. When you sign up, the console creates a default project with a bucket in it, so you can start right away. You can create as many projects as you need. * **Buckets** hold your data. A project can have many buckets. The bucket in your default project is named for you, for example `shelby-managed-account-1`. You choose the name of each bucket you create. * **Access keys** authenticate your requests. Each access key belongs to one bucket and can read and write only that bucket. A bucket can have more than one access key. An access key has two parts, which S3 tools ask for under their own names: | Part | What it is | In S3 tools | | ------------- | ---------------------------------------------- | ----------------- | | Access key ID | Identifies the key. It starts with `SHLB`. | Access key ID | | Secret | Signs your requests. Treat it like a password. | Secret access key | ### Sign in to the console Go to [console.shelby.xyz](https://console.shelby.xyz) and sign in, or sign up. Every account starts on the [Free plan](/protocol/pricing#free-plan). ### Copy a bucket name and its access key In the console, copy the name of the bucket you want to use, and the access key ID and secret of one of that bucket's access keys. To start, use the bucket in your default project. Anyone who has the secret, with its access key ID, can read and write that bucket. ### Make your first request ## Running at scale Have larger-scale requirements? Talk to our team about managed onboarding or how Shelby can support your use case. # Billing (/protocol/billing) This page covers the Paid plan. For rates and how usage is measured, see [Pricing](/protocol/pricing). ## Invoices and payments * Your billing month starts on the day you add your card. * At the start of each billing month, you get one invoice for the previous month's usage, covering all of your organizations. * Stripe emails your invoices and payment receipts. * Manage your card in **Console → Billing**. ## Failed payments If a payment fails, you have 30 days to pay before your account is blocked. Uploads and downloads keep working until then. | Day | What happens | | --- | ----------------------------------------------------------------------------- | | 0 | The payment fails, the grace period starts, and we email you. | | 23 | We email you a reminder. | | 29 | We email you a final reminder. | | 30 | If the invoice is still unpaid, your account is [blocked](#blocked-accounts). | | 60 | Your data is deleted. | To pay, add or update your card in **Console → Billing → Payment method**. The open invoice is charged automatically. Removing your card doesn't cancel your plan. Your next invoice fails, and the same grace period applies. To stop using Shelby, [cancel](#cancelling). ## Cancelling **Download anything you want to keep first.** Cancelling stops downloads straight away, and your data is deleted 30 days later. You can cancel at any time in the [console](https://console.shelby.xyz). Cancelling takes effect immediately: * Your account is [blocked](#blocked-accounts). * You get a final invoice for this month's usage so far. * Your account doesn't go back to the Free plan. ## Blocked accounts An account is blocked when a payment is still unpaid at the end of its grace period, or when it's cancelled. While an account is blocked, uploads and downloads don't work. Your data is deleted 30 days after your account is blocked. We email you before it's deleted. To reactivate your account, add a card in the console. If your data has already been deleted, you start with an empty account. # Overview (/protocol) Shelby is a data platform for distributed compute. It gives you one consistent place to store and read data from wherever your compute runs, using familiar S3-compatible tools. Shelby is built for workloads where: * Compute moves between locations, providers or environments. * Data is collected, processed or used for training in different places. * New compute creates more staging, copying or pipeline work. * The same dataset needs to serve multiple workloads. These challenges are particularly relevant to AI training and inference, large-scale data analytics and other data-intensive applications. Compute is dynamic, and the best location for a workload can change as capacity, performance and cost fluctuate. Shelby reduces the operational complexity and cost of moving between environments by reducing the need to repeatedly stage, copy and synchronize datasets. Teams can choose the compute that best suits each workload without rebuilding their data infrastructure each time. ## What's under the hood * **One address, global access.** A single global namespace lets workloads read the same data through the same S3-compatible interface. By default, data is stored in the `default` location, which spreads it across all of our datacenters, so you don't manage separate regional copies. * **Efficient erasure coding.** Data is encoded across many storage nodes to support durability and recovery without the overhead of storing complete replicas. * **Integrity checks on every write.** Uploads are checked against `Content-MD5` when you send it, and ETags are MD5s, so you can confirm the bytes that arrived are the bytes you sent. * **High-performance data access.** Shelby is designed for data-intensive workloads across distributed compute environments. * **Built by experienced teams.** Shelby is built by teams from Jump Trading Group and Aptos Labs, with years of experience in high-performance storage and globally distributed systems. [How Shelby stores data](/protocol/architecture/overview) goes into more detail. ## Ways to use Shelby Ready to try it? Start with the [Quickstart](/protocol/quickstart). # Pricing (/protocol/pricing) Every account starts on the Free plan, with no card. Add a card to move to the Paid plan, which charges only for what you use. Prices are in US dollars. | | Free plan | Paid plan | | ------------- | -------------------------------- | ---------------------------------------------------- | | Storage | 10 GiB | $20 per TiB-month | | Egress | 10 GiB a month | 3× your average storage each month, then $10 per TiB | | Usage caps | Yes, and nothing is ever charged | None | | Minimum fee | — | None | | Card required | No | Yes | | Billing | — | Monthly, for the previous month's usage | Storing more than 10 TiB, or need custom terms? See [Enterprise](#enterprise). ## Free plan The Free plan has no time limit, and your data stays as long as you like. * **10 GiB of storage.** An upload that would take you past it is refused with `400 EntityTooLarge` before any data is sent. Delete objects or upgrade to upload more. * **10 GiB of egress a month.** The allowance renews each month on the date you signed up. Once it's used up, downloads are blocked until it renews or you upgrade. These are hard caps, so the Free plan never charges you. ## Paid plan Add a card in the [console](https://console.shelby.xyz) when you sign up, or at any time after. Billing starts from the first byte: the Free plan's 10 GiB doesn't carry over. There's no minimum fee. $20 is the rate per TiB-month, not a monthly minimum: 100 GiB stored for a month costs about $2. There are no caps on how much you store or download. A Paid account is blocked only when an invoice is still unpaid at the end of its grace period, or when you cancel. See [Billing](/protocol/billing). The [concurrent download limit](/tools/s3-gateway/limits#concurrent-downloads) still applies, because it limits how many downloads run at once, not how much you download. ## How usage is measured ### Storage Storage is billed in TiB-months. One TiB-month is 1 TiB stored for 730 hours, the average length of a month, and costs $20. Every hour, Shelby measures how much you have stored: the objects you've uploaded, plus the parts of multipart uploads still in progress. Your invoice adds those measurements up into TiB-months, so you pay for what you stored, for as long as you stored it. For example: * 512 GiB for a whole month costs about $10, and so does 1 TiB for 15 days. * 2 TiB for 365 hours and 0.5 TiB for 1,460 hours are each 1 TiB-month, or $20. Objects you delete stop counting from the next hourly measurement. Billing months vary in length, because each one runs from the day of the month you added your card. 1 TiB stored for a whole billing month costs $18.41 in a 28-day month and $20.38 in a 31-day one, which averages $20 over a year. The parts of an unfinished multipart upload are billed as storage until you complete or abort the upload, and Shelby has no lifecycle rules to clean them up for you. In the AWS SDK for JavaScript, `ListMultipartUploads` can't find them, so abort each upload you start if it fails. See [Known compatibility issues](/tools/s3-gateway/known-issues). ### Egress Egress is data downloaded from Shelby. Every GET counts, including range requests and downloads through [presigned URLs](/tools/s3-gateway/presigned-urls), and downloading the same object again counts again. Each billing month, your egress allowance is 3× your average storage for that month. Egress beyond it costs $10 per TiB. Unused allowance doesn't roll over. The allowance depends on your average storage over the whole month, so data stored all month earns a full allowance and data uploaded late in the month earns less. Partway through the month, the allowance and any overage the console shows are provisional. The final numbers are calculated on your bill date. For example, in a 30-day billing month, you store nothing for 15 days, then on day 16 you upload 1 TiB and download 2 TiB. On day 16 your average storage is close to zero, so the console shows almost all 2 TiB as projected overage. By the bill date your average storage is 0.5 TiB, so your allowance is 1.5 TiB, and you pay for 0.5 TiB of overage: $5. ### The 10 MiB minimum Every object, and every part of a multipart upload, counts as at least 10 MiB of storage. Objects of 10 MiB or more count at their actual size. For example, 1,000 objects of 8 MiB hold about 7.81 GiB but count as about 9.77 GiB. So that large files count at close to their actual size, upload them in parts of at least 10 MiB. The last part can still be smaller, and counts as 10 MiB. Several S3 clients default to smaller parts. See [Choosing a part size](/tools/s3-gateway/limits#choosing-a-part-size). On the Free plan, counted storage is what fills your 10 GiB. On the Paid plan, you're billed for the actual bytes you store and download, so the minimum doesn't change your invoice. The console shows counted storage, so it can show more than you're billed for. ### Units Pricing, the console and invoices use binary units: 1 GiB is 1,024 MiB, and 1 TiB is 1,024 GiB. ## Examples Each example assumes storage stays the same for a whole billing month of average length (730 hours). | Stored | Egress | Storage charge | Egress allowance | Egress charge | Total | | ------- | ------- | -------------- | ---------------- | ------------------ | --------------- | | 1 TiB | 2 TiB | $20 | 3 TiB | $0 | **$20** | | 1 TiB | 4 TiB | $20 | 3 TiB | 1 TiB × $10 = $10 | **$30** | | 1.5 TiB | 5 TiB | $30 | 4.5 TiB | 0.5 TiB × $10 = $5 | **$35** | | 100 GiB | 200 GiB | About $1.95 | 300 GiB | $0 | **About $1.95** | ## Enterprise There's no separate team plan, because the Paid plan has no usage caps. If you're storing more than 10 TiB, or need custom features or terms, talk to us about enterprise pricing. # Quickstart (/protocol/quickstart) ## Already using S3? Point your existing S3 client at Shelby. For most code, only the client configuration changes: ```python s3 = boto3.client( "s3", endpoint_url="https://s3.beta.shelby.xyz", # [!code ++] aws_access_key_id=SHELBY_ACCESS_KEY_ID, # [!code ++] aws_secret_access_key=SHELBY_SECRET_ACCESS_KEY, # [!code ++] region_name="default", # [!code ++] config=Config( s3={"addressing_style": "path"}, # [!code ++] request_checksum_calculation="when_required", # [!code ++] ), ) ``` Get your bucket name, and an access key ID and secret for that bucket, at [console.shelby.xyz](https://console.shelby.xyz), then follow the quickstart for your client: Each quickstart also has a runnable version in [shelby-quickstart](https://github.com/shelby/shelby-quickstart). Before moving a production workload, read [how Shelby differs from S3](/tools/s3-gateway#how-shelby-differs-from-s3). ## Using an AI agent? The [MCP server](/tools/mcp) gives Claude, Cursor or your own agent read and write access to your buckets, with no integration code. ## Learn more * [How Shelby stores data](/protocol/architecture/overview) * [Compatibility matrix](/tools/s3-gateway/compatibility) # Docs for AI agents (/tools/ai-llms) Shelby documentation provides two methods for programmatic access optimized for AI agents and LLMs. ## Full Documentation Endpoint Get all documentation in a single plain text file. ```bash curl https://docs.shelby.xyz/llms-full.txt ``` The response includes all pages formatted as: ```text # Page Title (URL) Page content in markdown... # Next Page Title (URL) Next page content... ``` ## Individual Page Markdown ### Direct URL Access any page's markdown content by appending `.mdx` or `.md` to the page URL: ```bash curl https://docs.shelby.xyz/tools/s3-gateway.mdx # or curl https://docs.shelby.xyz/tools/s3-gateway.md ``` Examples: * `/tools/s3-gateway` → `/tools/s3-gateway.mdx` or `/tools/s3-gateway.md` * `/protocol/quickstart` → `/protocol/quickstart.mdx` or `/protocol/quickstart.md` * `/tools/mcp` → `/tools/mcp.mdx` or `/tools/mcp.md` ### Accept Header Alternatively, request any documentation page as markdown by setting the `Accept` header to `text/markdown`: ```bash curl -H "Accept: text/markdown" https://docs.shelby.xyz/protocol/quickstart ``` This works for all documentation sections: * `/protocol/*` - Getting started and how Shelby works * `/tools/*` - The S3 API and MCP server ## Runnable examples and agent skills Two repositories are written for agents to read alongside these docs: * **[shelby-quickstart](https://github.com/shelby/shelby-quickstart)** has a runnable, self-checking example for each client these docs cover. Its `AGENTS.md` lists where code written for Amazon S3 breaks on Shelby, and `make doctor` checks credentials before any code runs. * **[shelby-skills](https://github.com/shelby/shelby-skills)** packages the same guidance as an agent skill, so the agent has it while working in your project. # MCP server (/tools/mcp) The Shelby MCP server exposes Shelby storage as tools your agent can call directly, so an agent can manage buckets and upload and download files without you writing any integration code. It acts with an agent key: a key you create in the console, limited to the buckets and access you choose. ## Create an agent key On the **Integrations** page of the [console](https://console.shelby.xyz), create an agent key and choose its: * **Name**: which agent will use it, so you can tell your keys apart later. * **Scope**: which buckets the agent can reach. * **Access**: read and write, or read-only. * **Expiry**: 30, 60, 90 or 180 days. | Scope | What the agent can reach | | ------------------ | ---------------------------------------------------------------------------------------------------- | | Whole organization | Every bucket in your organization. It can create buckets. | | Some projects | Every bucket in the projects you check, including new ones. It can create buckets in those projects. | | Specific buckets | Only the buckets you check. It can't create buckets. | | Access | What the agent can do | | -------------- | -------------------------------------------------------------------------------------------------------------- | | Read and write | Everything you can do with those buckets, including uploading files and deleting a bucket and everything in it | | Read-only | List and download files. It can't change anything. | Give an agent the least it needs. A read-only key scoped to specific buckets can't delete anything, whatever the agent is asked to do. The console shows the key once, when you create it. It starts with `shelbyagent_`. Treat it like a password: anyone who has it gets the access you gave the agent. ## Add Shelby to your agent client Don't put the key in a project-level MCP config. It's easy to commit. Use the one in your home directory, as every setup below does. `--allow-dir` names the directories the server may use: uploads read only from them, and downloads write only to them. Replace `/path/to/your/files` with the absolute path of a directory that exists. To allow more than one, list each after `--allow-dir`. [Add to Cursor](cursor://anysphere.cursor-deeplink/mcp/install?name=shelby\&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyJAc2hlbGJ5LXByb3RvY29sL21jcEBsYXRlc3QiLCItLWFsbG93LWRpciIsIi9wYXRoL3RvL3lvdXIvZmlsZXMiXSwiZW52Ijp7IlNIRUxCWV9BR0VOVF9LRVkiOiI8eW91ciBhZ2VudCBrZXk%2BIn19) installs the server with placeholders: replace `` and `/path/to/your/files` with your own. Or add it to `~/.cursor/mcp.json` yourself: ```json title="~/.cursor/mcp.json" { "mcpServers": { "shelby": { "command": "npx", "args": [ "@shelby-protocol/mcp@latest", "--allow-dir", "/path/to/your/files" ], "env": { "SHELBY_AGENT_KEY": "" } } } } ``` ```bash claude mcp add shelby --scope user \ --env SHELBY_AGENT_KEY='${SHELBY_AGENT_KEY}' \ -- npx @shelby-protocol/mcp@latest --allow-dir /path/to/your/files ``` `--scope user` saves the server to `~/.claude.json`, outside your project. The single quotes save `${SHELBY_AGENT_KEY}` itself rather than your key, and Claude Code fills it in from your environment when it starts the server. Export `SHELBY_AGENT_KEY` in your shell profile, such as `~/.zshrc`, before you start Claude Code. Download the [Shelby extension](https://console.shelby.xyz/downloads/shelby.mcpb) and open it. Claude Desktop asks for your agent key and the directories the server may use. ```toml title="~/.codex/config.toml" [mcp_servers.shelby] command = "npx" args = ["@shelby-protocol/mcp@latest", "--allow-dir", "/path/to/your/files"] # The first start downloads the package, which can take longer than the 10-second default. startup_timeout_sec = 60 [mcp_servers.shelby.env] SHELBY_AGENT_KEY = "" ``` ```json title="~/.gemini/settings.json" { "mcpServers": { "shelby": { "command": "npx", "args": [ "@shelby-protocol/mcp@latest", "--allow-dir", "/path/to/your/files" ], "env": { "SHELBY_AGENT_KEY": "" } } } } ``` The `npx` setups need Node.js 22.12 or later. ## Keep the key out of config files On macOS and Linux, the `npx` setups can read the key from your system's secret store instead, so no config file holds it. Store it under the service `shelby-mcp` and the account `SHELBY_AGENT_KEY`: ```bash security add-generic-password -U -s shelby-mcp -a SHELBY_AGENT_KEY -w ``` `security` prompts for the key, so it stays out of your shell history. `-U` replaces a key you stored before. ```bash secret-tool store --label="Shelby agent key" service shelby-mcp account SHELBY_AGENT_KEY ``` `secret-tool` prompts for the key. It needs a running secret service, such as GNOME Keyring. Then leave `SHELBY_AGENT_KEY` out of your setup: drop the `env` block, Codex's `[mcp_servers.shelby.env]` table, or Claude Code's `--env` line. A `SHELBY_AGENT_KEY` environment variable, even one still set to a placeholder, takes precedence over the secret store. The server reads the key when it starts, so restart your agent client after you replace it. The Claude Desktop extension asks for the key itself, so this doesn't apply to it. ## Expiry and revoking From a week before a key expires, the server tells your agent, so it can remind you. To keep the agent working, create a new key and replace the old one in your config or secret store. Revoke a key on the Integrations page as soon as an agent no longer needs it, or if it leaks. The key acts for you. If you leave the organization, it stops working. If you're a Viewer in the organization, it can't make changes. ## What it's good for * **Agent memory**: persistent recall across sessions. * **Dataset access**: let an agent read training shards directly. * **Artifact handoff**: write model outputs somewhere durable. ## Prefer code? The [S3 API](/tools/s3-gateway) works with the AWS CLI, boto3, rclone, DuckDB and any other S3 client. # How Shelby stores data (/protocol/architecture/overview) You don't need any of this to use Shelby: the S3 API handles it for you. It's here for when you want to know what your data goes through. ## Where your data lives Shelby runs storage nodes in our own datacenters, connected by a private network. By default, objects go to the `default` location, which spreads them across all of our datacenters. Every request, from anywhere, goes to the same endpoint and sees the same namespace. ## Writing an object When you upload an object: 1. The S3 endpoint receives it and checks it against `Content-MD5`, if you sent one. 2. The object is split into fixed-size pieces, and each piece is erasure-coded (below). 3. The coded chunks are written to a group of storage nodes. 4. Once every node has confirmed its chunks, the write is committed and your PUT returns. Because the PUT waits for that commit, writes take longer than on Amazon S3. Once it returns, reads see the new object straight away, though it can take a few seconds to appear in listings. [Known compatibility issues](/tools/s3-gateway/known-issues) explains how to handle that in code. Every object is encrypted at rest with keys Shelby manages. There's nothing to configure. ## Erasure coding Rather than keeping several full copies of your data, Shelby uses erasure coding, the same family of techniques large storage systems use to stay durable without the cost of full replication. Each piece of an object becomes 16 chunks: 10 that hold the data and 6 parity chunks computed from it. Any 10 of the 16 are enough to rebuild the piece, so it survives the loss of up to 6 storage nodes at once. That costs 1.6 times the original size, where three full copies would cost 3 times. Shelby uses [Clay codes](https://www.usenix.org/system/files/conference/fast18/fast18-vajha.pdf), which repair a lost chunk by reading a small part of many chunks rather than 10 whole ones. That cuts the network traffic needed for recovery by up to 4 times compared with standard Reed-Solomon codes. ## Reading an object When you read an object, the S3 endpoint finds the storage nodes that hold its chunks, fetches enough of them over the private network to rebuild the bytes you asked for, checks them, and returns them. Range reads fetch only the pieces that cover the range. ## Coordination Shelby keeps track of which objects exist and where their chunks are on the Aptos blockchain, which acts as its coordination layer. You never interact with it directly: an access key and the S3 API are all you need. ## Going deeper The [white paper](/protocol/architecture/white-paper) describes the original protocol design in full. # White paper (/protocol/architecture/white-paper) import { ExternalLink } from 'lucide-react'; The white paper describes the original design of the Shelby protocol: its architecture, erasure coding, and the research behind them. Shelby as you use it today, through the S3 API and an access key, is described in [How Shelby stores data](/protocol/architecture/overview). # Compatibility (/tools/s3-gateway/compatibility) Shelby implements the S3 calls that object storage workloads use: put, get, head, range reads, multipart uploads, listing and delete. This page lists how Shelby handles every part of the S3 API, so you can check your workload before you move it. Each row is marked: * **Supported**: works as it does on Amazon S3. * **Supported with differences**: works, with a difference noted alongside it. * **Not supported**: not available. The notes give the alternative. ## S3 features {/* GENERATED FRAGMENT. Do not edit by hand. Source: data/s3-compat.json, checked against the beta-harness corpus. Regenerate: pnpm generate:s3 */} ### Objects | Capability | Status | Notes | | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | PutObject, GetObject, HeadObject | Supported | Single PUTs up to 5 GiB. Range reads are supported. | | Read-after-write consistency | Supported with differences | GET and HEAD see a new or overwritten object as soon as the write returns. A new object can take a few seconds to appear in listings. See [Known compatibility issues](/tools/s3-gateway/known-issues). | | Overwrite an existing key | Supported | A plain PUT replaces the object, as a full new write. Reads see the new version as soon as the PUT returns. | | Create-only writes (`If-None-Match: *`) | Supported | Returns `412 PreconditionFailed` if the key already exists. | | Conditional overwrite (`If-Match` on PUT) | Not supported | Not enforced on the hosted endpoint yet: the write succeeds whether or not the ETag matches. Do not rely on it for concurrency control. See [Known compatibility issues](/tools/s3-gateway/known-issues). | | Conditional reads (`If-Match`, `If-None-Match`, `If-Modified-Since`, `If-Unmodified-Since`) | Not supported | Accepted and ignored. GET always returns the full object. | | DeleteObject | Supported | Returns `204`, including for a key that does not exist. `If-Match` supports exact ETags and `*` for an existence check. | | DeleteObjects (batch, up to 1,000 keys) | Supported with differences | Up to 1,000 keys. Keys that do not exist are reported as deleted, as on S3. Per-key ETags are supported and failed conditions return per-key errors. The AWS SDK for JavaScript sends this request in a form Shelby does not recognise yet. See [Known compatibility issues](/tools/s3-gateway/known-issues). | | CopyObject, UploadPartCopy, `aws s3 mv` | Not supported | Returns `501 NotImplemented`. Download and re-upload instead. | ### Multipart uploads | Capability | Status | Notes | | -------------------------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Create, UploadPart, Complete, Abort, ListParts, ListMultipartUploads | Supported with differences | Parts are 5 MiB to 5 GiB. `ListMultipartUploads` from the AWS SDK for JavaScript gets the wrong answer. See [Known compatibility issues](/tools/s3-gateway/known-issues). | | Parts per upload | Supported with differences | Up to 3,000 parts (S3 allows 10,000). Use parts of at least 10 MiB, which fit files up to about 29 GiB. | ### Listing | Capability | Status | Notes | | -------------------------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ListObjects, ListObjectsV2 | Supported with differences | Prefix, delimiter and pagination work. `max-keys` above 1,000 is rejected rather than clamped. `fetch-owner` is ignored. New objects can take a few seconds to appear. | ### Integrity | Capability | Status | Notes | | -------------------------------------------------------------- | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ETags | Supported | MD5 of the content for single-part objects, S3's `-` form for multipart objects. Objects written before mid-October 2026 have older ETags that are not MD5s. | | `Content-MD5` upload check | Supported | A mismatch is rejected with `400 BadDigest`. | | Flexible checksums (`x-amz-checksum-*`, `aws-chunked` uploads) | Not supported | Checksum headers are accepted but not verified. `aws-chunked` uploads, which the AWS CLI and boto3 send by default, are refused with `501`: each [quickstart](/tools/s3-gateway/quickstarts/aws-cli) shows the one setting that turns them off. | ### Object metadata | Capability | Status | Notes | | --------------------------------------------------------------------------------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | | Content-Type, Cache-Control, Content-Disposition, Content-Encoding, Content-Language, Expires | Supported | Stored and returned. Objects stored before Shelby kept metadata come back as `binary/octet-stream`. | | User metadata (`x-amz-meta-*`) | Supported | Stored and returned, up to 2 KB per object as on S3. This includes the modification time rclone writes. | | Object tagging, storage classes, object lock | Not supported | Headers are accepted and ignored. Every object is `STANDARD`. The tagging, retention and legal-hold APIs are refused. | ### Security and access | Capability | Status | Notes | | ---------------------------------------- | ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | AWS Signature Version 4 | Supported | Header-signed requests from any S3 client, with any signing region. Presigned URLs must be signed with `default`. Use `default` everywhere: it's the region Shelby reports. | | Server-side encryption | Supported with differences | Always on: every object is encrypted at rest with keys Shelby manages (SSE-S3). SSE-C and SSE-KMS are refused with `501`. | | Presigned URLs for downloads (GET, HEAD) | Supported | One object per URL, for up to 7 days. Sign with region `default`. See [Presigned URLs](/tools/s3-gateway/presigned-urls). | | Presigned uploads, deletes and listings | Not supported | Refused with `405` or `400`. Upload, delete and list from a server with your credentials. To share a prefix, use a [folder share](/tools/s3-gateway/presigned-urls#share-a-folder). | | CORS and browser uploads | Not supported | You can't configure CORS. Browsers can open presigned links and load them in `` and `