Buckets for files your users upload. Volumes for disks that outlive machines.
S3-compatible buckets with presigned URLs and CORS, so a browser uploads straight to storage. Attach a bucket to an app and it gets a key for that bucket alone. Volumes keep an app's data through deploys and stops, with snapshots to object storage on a cadence you set.
ry bucket create my-uploads
Storage, in detail.
Presigned URLs
Ask the API for a URL valid for one object, one method and a limited time. Whoever holds it needs no key. The answer names the headers the call must send exactly.
Attached, not configured
ry bucket attach gives the app a key that opens exactly this bucket, read and write, and injects S3_BUCKET, S3_ENDPOINT, S3_REGION and the key as managed secrets.
Uploads from the browser
ry bucket cors-set writes one rule for your origin with GET, PUT and HEAD and ETag exposed. CORS is not authentication: the signature protects the object.
Volumes that outlive machines
A volume outlives a stop, a deploy and a replaced machine. Attach it to an app, grow it, detach it; the data stays.
Snapshots on a cadence
A volume is snapshotted to object storage on a cadence you set, daily by default, down to every 15 seconds. ry volume update changes it without a restart.
Home disks
A computer from the CLI or the console keeps /data on a volume. It is kept while the computer is shut down and when its machine is replaced.
A bucket, an upload, a volume.
Create the bucket, sign an upload, attach it. The same for a volume.
ry bucket create my-uploads ry bucket presign my-uploads reports/2026-10.pdf --put --content-type application/pdf ry bucket attach my-uploads --to web # S3_* as managed secrets ry bucket cors-set my-uploads --allow-origin https://www.example.com ry bucket ls my-uploads --prefix reports/ ry volume create data --size 20 ry volume attach data --to web ry volume resize data 50 # only upwards
curl -X POST https://api.rytiv.com/v1/buckets \
-H "Authorization: Bearer $RYTIV_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "my-uploads"}'
curl -X POST https://api.rytiv.com/v1/buckets/my-uploads/presign \
-H "Authorization: Bearer $RYTIV_TOKEN" \
-H "Content-Type: application/json" \
-d '{"op": "put", "key": "reports/2026-10.pdf",
"contentType": "application/pdf", "expiresInS": 900}'
# url, method, expiresAt, requiredHeaders: send them exactly
curl -X POST https://api.rytiv.com/v1/volumes \
-H "Authorization: Bearer $RYTIV_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "data", "sizeGb": 20}' The bounds, as the platform enforces them.
Limits
- Bucket name
- 3 to 63 characters, unique within a region
- Presigned URL
- 1 second to 7 days, default 15 minutes
- Object key
- up to 1024 bytes
- CORS rules per bucket
- 100
- Objects per list page
- 100 default, 1000 at most
- Volume size
- 1 to 500 GB; grows, never shrinks
- Volume snapshot cadence
- daily default, at least 15 s and 3 s per GB
- Machines with a volume
- exactly 1 per app
Every bound is on Limits and quotas. A request outside them answers 400 with bad-request and names the field.
Errors you will meet
| 409 | name-takenThe bucket name is taken in this region, or your team already has this volume name |
| 409 | conflictThe bucket still holds objects; --force deletes them first |
| 409 | volume-needs-single-machineAn app with a volume runs exactly one machine |
| 403 | token-scopeThe key's scopes do not cover this route |
Every error is JSON with a sentence and a stable code. Branch on code. See the error catalog.
100 GB of objects: €2.20 per month. A 20 GB volume: €2 per month. Outbound transfer is not billed.
For businesses and freelancers. All prices excluding VAT. Prepaid credit in euros, no plans, no seats. Introductory pricing until 31 January 2027. Pricing
What developers ask about Storage.
Answers from the documentation. The Buckets guide has the rest.
Does my S3 client work?
Yes, with the S3_* variables an attachment injects; the endpoint supports virtual-host addressing. With the JavaScript S3 SDK from version 3.729, set requestChecksumCalculation to WHEN_REQUIRED, or presigned uploads fail with InvalidDigest.
How do I attach a second bucket to the same app?
With a prefix: ry bucket attach my-uploads --to web --as uploads gives UPLOADS_S3_BUCKET and so on. From the second bucket on an app the prefix is required.
What happens to objects when I detach?
They stay. ry bucket detach removes the variables and revokes the key. Attaching again rotates the key; it is shown once, in the attach answer.
Why does a browser upload fail?
A browser sends a preflight first; without a CORS rule the storage refuses it and nothing reaches your server. ry bucket cors-set allows your origin.
Can I grow a volume?
Yes. ry volume resize grows it, and the new size takes effect at the next cold start of its app; a stop and start is enough.
On the same API, the same bill.
Create a bucket.
Object storage at €0.022 per GB-month, outbound transfer included.
claude mcp add --transport http rytiv https://api.rytiv.com/v1/mcp --header "Authorization: Bearer <your key>"
For businesses and freelancers, from a solo developer to a team. Pricing