Stow stores a file and gives back a public URL:
https://stow.sh/{26-character id}/{filename}. Anyone with the link can open
the file; nobody can list or guess links. Give the user the URL exactly as
returned.
Pick a route
- Stow MCP tools available (
put_file,put_text,put_from_url,create_upload_url,list_files,delete_file,transform_url,get_account): use them. They are signed in already. - A
stowcommand on PATH: use the CLI (below). - Otherwise: use the HTTP API with curl (below).
The CLI and API need an API key. Look in STOW_TOKEN, then
~/.config/stow/token. If neither exists, ask the user to create a key at
https://stow.sh/account (under API keys) and save it to
~/.config/stow/token with chmod 600. Never print the key or put it in a
file that gets committed.
Upload
With the CLI:
stow put ./render.png # prints the URL
stow put a.jpg b.mp4 # one URL per line
stow put https://example.com/x.jpg # re-host a remote file
stow put ./clip.mp4 --json # { url, key, size, contentType }
With curl:
TOKEN="${STOW_TOKEN:-$(cat ~/.config/stow/token)}"
curl -sS -T ./render.png -H "Authorization: Bearer $TOKEN" \
https://stow.sh/api/files/render.png
# => {"url":"https://stow.sh/.../render.png","key":"...","size":1234,"contentType":"image/png"}
The last part of the path becomes the filename in the link, so URL-encode it. The extension sets the content type. To re-host a remote file without the CLI or MCP, download it first, then upload it.
Limits and errors
Files can be up to 100 MB. A Personal plan holds 10 GB and a Studio plan
100 GB. Errors come back as {"code", "error"}:
| Status and code | What to do |
|---|---|
401 unauthorized |
The key is missing, wrong or revoked. Ask for a new one. |
402 payment_required |
The account has no plan. Tell the user to subscribe at https://stow.sh/account. Don't retry. |
413 too_large |
Over 100 MB. Compress or trim it, or link the source instead. |
413 storage_full |
The plan is full. Tell the user; they can delete files or move to Studio. |
404 not_found |
No such file, or not theirs. |
CLI exit codes: 1 failed (retry once), 2 bad request, too large or storage
full, 3 not found, 4 no key, unauthorised or no plan. With --json, stderr
gets {"error": {"code", "status", "message"}}.
Transforms
Add query params to any Stow URL. stow url <url> w=800 f=avif builds one,
or the transform_url tool. Results are cached, so the same URL is cheap the
second time. Unknown params are ignored.
A transform that can't be applied serves the original file instead. Before
handing over a thumbnail or poster, check with a GET (HEAD never transforms):
curl -s -o /dev/null -D - '<url>' | grep -i x-stow-transform gives ok for
a variant and original for a fallback.
Images:
| Param | Values |
|---|---|
w, h |
pixels, up to 4096 |
q |
1-100, default 80 |
f |
webp (default), avif, jpeg, png |
fit |
scale-down (default), contain, cover, crop, pad |
gravity |
auto (subject-aware), face, left, right, top, bottom, center |
trim |
border removes flat borders |
Videos (MP4 H.264, up to 100 MB and 10 minutes):
| Param | Values |
|---|---|
w, h |
pixels, 10-2000 |
fit |
contain (default), cover, scale-down |
t |
start time: 5, 5s, 500ms, 1m |
d |
duration, same format |
audio=false |
silent MP4 |
mode |
video (default), frame (still), spritesheet, audio (M4A) |
f |
jpg or png for mode=frame |
count |
frames in a spritesheet |
Common recipes:
- Thumbnail:
?w=400&h=400&fit=cover&gravity=auto - Poster frame for a video:
?mode=frame&t=1s&w=1280 - Small preview clip:
?w=480&t=0&d=5s&audio=false
For playback in a <video> tag, use the untransformed URL: it seeks
everywhere, while a transformed clip only does once cached. There is no HLS;
for long videos, link the original.
List and delete
stow rm https://stow.sh/{id}/{filename}
curl -sS -H "Authorization: Bearer $TOKEN" https://stow.sh/api/files
curl -sS -X DELETE -H "Authorization: Bearer $TOKEN" \
https://stow.sh/api/files/{id}/{filename}
Only the account that uploaded a file can delete it. Resized copies can keep serving from caches for a while after a delete, so treat a shared link as published.