What you get
Per project: an S3-compatible bucket, accessed through MIOSA endpoints. Credentials injected as env vars:
STORAGE_BUCKET=miosa-proj_xxx-uploads
STORAGE_ENDPOINT=https://storage.miosa.app
STORAGE_KEY_ID=...
STORAGE_KEY_SECRET=... Your code uses the standard S3 client libraries:
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3"
const s3 = new S3Client({
endpoint: process.env.STORAGE_ENDPOINT,
credentials: {
accessKeyId: process.env.STORAGE_KEY_ID!,
secretAccessKey: process.env.STORAGE_KEY_SECRET!,
},
region: "us-east-1",
})
await s3.send(new PutObjectCommand({
Bucket: process.env.STORAGE_BUCKET,
Key: "uploads/foo.png",
Body: pngBuffer,
})) Use it your way — API, CLI, or SDK
No SDK required. Same bucket, three ways.
Storage calls need an API key with the
storage:read/storage:writescope. Mint one withPOST /api/v1/api-keys {"scopes": ["storage:read","storage:write"]}. A plain key gets a 403 telling you which scope is missing.
Raw API (curl):
# Create a bucket
curl -X POST https://api.miosa.ai/api/v1/storage/buckets
-H "Authorization: Bearer $MIOSA_API_KEY" -H "Content-Type: application/json"
-d '{"name": "my-bucket"}'
# Upload an object (binary → application/octet-stream)
curl -X PUT "https://api.miosa.ai/api/v1/storage/buckets/BUCKET_ID/objects/path/file.txt"
-H "Authorization: Bearer $MIOSA_API_KEY"
-H "Content-Type: application/octet-stream" --data-binary @file.txt
# Download it
curl "https://api.miosa.ai/api/v1/storage/buckets/BUCKET_ID/objects/path/file.txt"
-H "Authorization: Bearer $MIOSA_API_KEY"
# Presign a URL so a browser can upload/download directly (no proxy)
curl -X POST "https://api.miosa.ai/api/v1/storage/buckets/BUCKET_ID/presign"
-H "Authorization: Bearer $MIOSA_API_KEY" -H "Content-Type: application/json"
-d '{"key": "path/file.txt", "method": "GET"}' CLI:
miosa storage create --name my-bucket
miosa storage list
miosa storage upload <bucket-id> ./file.txt
miosa storage objects <bucket-id>
miosa storage download <bucket-id> path/file.txt
miosa storage presign <bucket-id> path/file.txt Signed URLs for browser uploads
Don’t proxy file uploads through your runtime. Mint a signed URL server-side; the browser uploads directly to storage:
// Server
const url = await miosa.storage.signedUrl({
bucket: process.env.STORAGE_BUCKET!,
key: `users/${userId}/avatar.png`,
operation: "put",
expiresInSec: 300,
contentType: "image/png",
})
return { uploadUrl: url } // Browser
await fetch(uploadUrl, {
method: "PUT",
body: file,
headers: { "Content-Type": "image/png" },
}) Same pattern for downloads (operation: "get"). Signed URLs are scoped (single key, single operation, short expiry) - no risk of leaking bucket-wide credentials to a browser.
Public vs private
Each object can be private (default; access only via signed URL) or public (served from a *.storage.miosa.app URL). Public objects can also be fronted by a custom domain via your project’s Domain settings.
Bandwidth and storage costs
Two billable dimensions:
- Storage - GB-month for stored bytes.
- Egress - GB out from MIOSA to the public internet. Storage-to-runtime within MIOSA is free.
Attribution is carried on every event for chargeback.
Limits
| Limit | Default | Tunable |
|---|---|---|
| Storage per project | 1 GB | Yes (plan-dependent) |
| Direct API upload size | 5 MB verified | Larger uploads should use presigned/direct storage |
| Max object size | 5 GB target | Up to 100 GB target for multipart |
| List keys per call | 1000 | Standard S3 pagination |
Sandboxes can use the bucket too
The same env vars are injected into sandboxes for dev / testing. Upload from inside a sandbox:
await sandbox.exec({
cmd: "aws",
args: ["s3", "cp", "/workspace/build.tar.gz", `s3://${process.env.STORAGE_BUCKET}/builds/`],
env: {
AWS_ACCESS_KEY_ID: process.env.STORAGE_KEY_ID,
AWS_SECRET_ACCESS_KEY: process.env.STORAGE_KEY_SECRET,
AWS_ENDPOINT_URL: process.env.STORAGE_ENDPOINT,
},
}) Bring your own bucket?
Yes. Set the env vars to point at an external S3-compatible bucket (real AWS, Backblaze B2, R2, etc.). MIOSA injects whatever you set.
Python SDK
See also
- Overview - the broader data plane
- Environments - per-env bucket names