You build the product.
Stow stores the media.
Private media storage as an API — isolated per account, quota-enforced, served through signed links. Enterprise media infrastructure behind one bearer token.
POST /upload-url · PUT bytes · POST /confirm — that's the whole integration
GET /i/stag.jpg?token=… — 200 OK · signed link Quick start
- 01
Create an account
Sign up — every account gets isolated storage on the free tier, instantly.
- 02
Mint an API key
Dashboard → API keys → Create. Shown once; it's your server-side credential.
- 03
Upload from anywhere
SLOT=$(curl -s -X POST "https://www.stow-io.com/api/media/upload-url" \ -H "X-Stow-Key: $STOW_API_KEY" -H "Content-Type: application/json" \ -d '{"filename":"photo.jpg","sizeBytes":123456,"mimeType":"image/jpeg"}') curl -X PUT "$(echo $SLOT | jq -r .uploadConfig.uploadUrl)" \ -H "Content-Type: image/jpeg" --data-binary @photo.jpg curl -X POST "https://www.stow-io.com/api/media/confirm/$(echo $SLOT | jq -r .assetId)" \ -H "X-Stow-Key: $STOW_API_KEY"
Building with an AI agent?
Copy the prompt and paste it into your agent — it carries everything the agent needs, including this deployment's real API URL.
build a photo gallery using Stow Or copy the full integration prompt
Integrate this app with the Stow media storage API. Onboard FIRST — do not write any integration code until steps 1 and 2 are done.
1. Fetch the full reference and follow it: https://www.stow-io.com/stow.txt
2. Get an API key via device pairing (the human just clicks Approve):
- POST https://www.stow-io.com/api/pair/start (no body) -> {deviceCode, userCode, verificationUrl}
- Open the verificationUrl in my browser for me (macOS: `open <url>`, Linux: `xdg-open <url>`, Windows: `start <url>`), and print it too in case that fails. The pairing code is pre-filled — WAIT while I log in and click Approve.
- Poll POST https://www.stow-io.com/api/pair/claim {deviceCode} every 3s until {status:"approved", apiKey}.
- Save apiKey to the project's gitignored .env as STOW_API_KEY. Keep it server-side only; never put it in frontend code.
3. Confirm the key works (GET https://www.stow-io.com/api/media/quota) before writing integration code.
Auth: send "X-Stow-Key: $STOW_API_KEY" on every request.
Endpoints (prefix https://www.stow-io.com):
- POST /api/media/upload-url body {filename, sizeBytes, mimeType} -> {assetId, uploadConfig.uploadUrl}
- then PUT the raw file bytes to uploadConfig.uploadUrl (NOT to the API)
- then POST /api/media/confirm/:assetId (required, or the upload expires in ~15 min)
- GET /api/media/files -> [{assetId, filename, sizeBytes, mimeType, createdAt}]
- GET /api/media/files/:assetId/download-url -> {downloadUrl} (signed, ~10 min TTL — store assetId, never the URL)
- DELETE /api/media/files/:assetId
- GET /api/media/quota -> {tier, quotaBytes, usedBytes, ...}
Handle: 401 invalid key, 409 filename exists (no overwrites — pick a new name),
413 over quota or file too large.
Filenames: letters, digits, spaces, . _ - ( ), no slashes, no leading dot, max 128 chars. Prefer a drop-in agent skill? Download the Stow skill ↓ or read the full machine reference at /stow.txt.
Out of the box
STORAGE API
- Isolated storage — every account gets its own folder; cross-account access doesn't exist in the API
- Signed delivery — files are private; reads happen through expiring signed links only
- Global CDN — media is served from edge locations worldwide, cached for fast low-latency delivery
- Quota enforcement — reserve → upload → confirm, reconciled against real stored bytes
- Tiers — free 100 MB, plus 50 GB, enterprise 1 TB
MANAGED PLATFORM
- Accounts & auth — member signup/login built in; API keys for servers and agents
- Web dashboard — capacity gauge, uploads, file browser with previews, key management
- Admin console — tiers, suspension, role-based access, full audit trail
- Enterprise media backend — the storage engine that serves billions of media requests
Storage is the start. The media does the rest.
Your files don't just sit in a bucket — transform and stream them on the fly, straight from the URL you store against. The demo below is a real transform, applied on delivery.
IMAGE TRANSFORMS
live · drag to transformVIDEO TRANSCODING
liveOne upload → every resolution, each in its own folder. This player streams the real transcoded files. Live via POST /files/:id/transcode.