Skip to main content

Image Delivery API

These endpoints synchronously return processed images or existing media objects and are suitable for browsers, CDNs, and upstream applications.

For the complete definitions of BASE_URL and HMAC_SECRET used by the signing examples below, see Configuration.

Endpoint overview

EndpointPurposeAuthBacking bucket
GET /img/{sig}/{opts}/{encoded_source}.{format}transform an image on demand and cache the resultHMAC-signed URLreads source bucket, writes image cache into media bucket
GET /original/{sig}/{encoded_key}proxy the original objectHMAC-signed URLsource bucket
GET /thumb/{sig}/{encoded_key}proxy an existing thumbnail or coverHMAC-signed URLmedia bucket

GET /img/{sig}/{opts}/{encoded_source}.{format}

Path shape

/img/{sig}/{opts}/{encoded_source}.{format}

Examples:

/img/<sig>/w640_h360_q80/uploads%2Favatars%2Fsample.jpg.webp
/img/<sig>/w1200/uploads%2Fproducts%2Fhero.png.avif

Parameter semantics

SegmentMeaning
sighex-encoded HMAC-SHA256 signature
optsimage options such as w640_h360_q80
encoded_sourceURL-escaped source object key
formatoutput format: webp, avif, jpg, png, or gif

Canonicalization rules

Vylux signs a canonical form, not the raw browser URL string:

  • opts are normalized into w -> h -> q order
  • encoded_source is decoded before signing
  • jpeg is normalized to jpg

Conceptually, the signature input is:

{canonical_options}/{decoded_source_key}.{canonical_format}

shell signing and curl example

BASE_URL='http://localhost:3000'
HMAC_SECRET='replace-with-hmac-secret'
OPTIONS='w640_h360_q80'
ENCODED_SOURCE='uploads%2Favatars%2Fsample.jpg.webp'
CANONICAL_SOURCE='uploads/avatars/sample.jpg.webp'

SIG="$(printf '%s/%s' "$OPTIONS" "$CANONICAL_SOURCE" \
| openssl dgst -sha256 -hmac "$HMAC_SECRET" -hex \
| sed 's/^.* //')"

curl -L "$BASE_URL/img/$SIG/$OPTIONS/$ENCODED_SOURCE"

Successful response behavior

  • 200 OK
  • Content-Type matches the output format
  • Cache-Control: public, max-age=31536000, immutable
  • ETag derived from the returned bytes

Failure semantics

StatusMeaning
400invalid options, invalid source encoding, or unsupported output format
403invalid signature
404source object not found
422source exists but cannot be processed
502source storage temporarily unavailable
500internal processing failure

GET /original/{sig}/{encoded_key}

This endpoint proxies original objects from the source bucket without transforming them.

shell signing and curl example

BASE_URL='http://localhost:3000'
HMAC_SECRET='replace-with-hmac-secret'
ENCODED_KEY='uploads%2Fsample.mp4'
CANONICAL_KEY='uploads/sample.mp4'

SIG="$(printf '/%s' "$CANONICAL_KEY" \
| openssl dgst -sha256 -hmac "$HMAC_SECRET" -hex \
| sed 's/^.* //')"

curl -L "$BASE_URL/original/$SIG/$ENCODED_KEY"

Behavior notes

  • validates the HMAC before touching storage
  • infers Content-Type from extension first, then falls back to content sniffing
  • returns 404 when the object does not exist

GET /thumb/{sig}/{encoded_key}

This endpoint proxies existing thumbnails, video covers, or other static media objects from the media bucket.

shell signing and curl example

BASE_URL='http://localhost:3000'
HMAC_SECRET='replace-with-hmac-secret'
ENCODED_KEY='videos%2Fab%2Fabcdef%2Fcover.jpg'
CANONICAL_KEY='videos/ab/abcdef/cover.jpg'

SIG="$(printf 'thumb/%s' "$CANONICAL_KEY" \
| openssl dgst -sha256 -hmac "$HMAC_SECRET" -hex \
| sed 's/^.* //')"

curl -L "$BASE_URL/thumb/$SIG/$ENCODED_KEY"

Behavior notes

  • the thumb/ signing domain prevents signature reuse across /thumb and /original
  • successful responses include Access-Control-Allow-Origin: *

Practical guidance

  • never expose HMAC_SECRET to browsers or public clients
  • generate signed URLs in your upstream application or auth service
  • rely on stable object keys or content hashes so CDN caching stays predictable

Where the signer should live

In most deployments, the /img, /original, and /thumb signer should live in one of these trusted places:

  • your main application backend
  • a dedicated internal signing service
  • a trusted edge worker that can safely read HMAC_SECRET

The usual request flow is:

  1. the user asks your application for an image or asset
  2. your application checks whether that user may access the media record
  3. your application signs the Vylux URL server-side
  4. your application returns the final signed URL to the browser

That means browsers should receive only the final URL, never the secret and never the unsigned path.

If you are exposing generated covers, previews, or thumbnails from job results, convert the returned media-bucket key into a signed /thumb URL at that same trusted layer.