Image transforms

Serve a resized, re-encoded, or blurred version of a stored image straight from its URL. Transforms run under the same Row-Level Security as a normal Storage read, and every derivative is cached.

Endpoints

The render routes mirror the storage download routes — the bucket and object key are path segments, and the transform is given in the query string:

GET  /storage/v1/render/image/public/{bucket}/{path}
GET  /storage/v1/render/image/authenticated/{bucket}/{path}
GET  /storage/v1/render/image/sign/{bucket}/{path}?token=…

public serves objects from public buckets with no key (the bucket's public-read policy is the authorization); authenticated takes a bearer key or user token and resolves the object under that caller's RLS; sign serves a transform baked into a signed URL. A transform can never widen access — an object you could not download, you cannot render.

# a 400px-wide WebP thumbnail of a public avatar
https://<ref>.kethosbase.com/storage/v1/render/image/public/avatars/alice.png?width=400&format=webp

# authenticated: send the key/token as usual
curl "https://<ref>.kethosbase.com/storage/v1/render/image/authenticated/photos/2026/trip.jpg?width=800&height=800&resize=cover" \
  -H "Authorization: Bearer <key>"

Transform parameters

ParameterValuesDefault
widthpixels, up to 4096 (over is clamped)from height / source aspect
heightpixels, up to 4096 (over is clamped)from width / source aspect
resizecontain (fit, no crop) · cover (fill, centre-crop) · fill (stretch)contain
formatorigin · jpeg · png · webp · aviforigin (keep source type)
quality1–100 (ignored for PNG)80
blur0–100 (Gaussian radius)0 (none)

A bad value (a negative dimension, quality outside 1–100, an unknown resize or format) answers 400. A request that asks for no change streams the original bytes unchanged.

Caching, quotas, and limits

The first request for a given object-and-parameters combination computes the derivative and stores it; later requests are served from that cache. The cache is platform-managed and does not count against your project's storage. Rendered bytes are metered as egress just like a download, and a request that would exceed your egress allowance answers 429.

Signed transform URLs

To hand out a time-limited link to a specific rendered image — without exposing a key — mint a signed URL and include a transform block. The parameters are locked into the signed token, so the holder gets exactly that rendition and cannot change the object or the transform:

curl -X POST "https://<ref>.kethosbase.com/storage/v1/object/sign/photos/2026/trip.jpg" \
  -H "Authorization: Bearer <key>" \
  -H "Content-Type: application/json" \
  -d '{ "expiresIn": 3600,
        "transform": { "width": 1200, "format": "webp", "quality": 70 } }'

→ { "signedURL": "/storage/v1/render/image/sign/photos/2026/trip.jpg?token=…" }

Minting requires that the caller can read the object under RLS, and the transform must actually change the image (an identity transform is rejected). See Storage for signed URLs in general.