{"openapi":"3.1.0","info":{"title":"lorem.media","version":"1.0.0","description":"Free placeholder photos, video, and audio for developers. Hotlink directly into mockups, Storybook fixtures, marketing pages awaiting real content, and dev-tool demos. No signup, no API keys, no bandwidth caps. For your own content in production, see [0.media](https://0.media) — the paid sibling on the same R2-backed infrastructure.","contact":{"name":"lorem.media","url":"https://www.lorem.media"},"license":{"name":"MIT","url":"https://opensource.org/license/mit"}},"servers":[{"url":"https://www.lorem.media","description":"Production"}],"tags":[{"name":"media","description":"Media-byte redirect endpoints"},{"name":"manifests","description":"HLS master playlists and caption tracks"},{"name":"metadata","description":"JSON listings and per-asset info"},{"name":"cdn","description":"Direct asset byte serving"}],"paths":{"/photo":{"get":{"tags":["media"],"summary":"Random photo at the source's native size","description":"No-dimensions form. 302s to `/cdn/<key>` for the source rendition. For your own image hosting in production, see [0.media](https://0.media).","responses":{"302":{"$ref":"#/components/responses/MediaRedirect"}}}},"/photo/{width}/{height}":{"get":{"tags":["media"],"summary":"Random photo at the requested width","description":"Width is honored; height is a hint — the served image preserves the source aspect. `X-Image-Width`/`X-Image-Height` report the actual served dimensions.","parameters":[{"name":"width","in":"path","required":true,"schema":{"type":"integer","minimum":16,"maximum":4096}},{"name":"height","in":"path","required":true,"schema":{"type":"integer","minimum":16,"maximum":4096}},{"name":"category","in":"query","schema":{"$ref":"#/components/schemas/PhotoCategory"}}],"responses":{"302":{"$ref":"#/components/responses/MediaRedirect"},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/photo/seed/{seed}/{width}/{height}":{"get":{"tags":["media"],"summary":"Deterministic photo by seed","description":"Same seed always resolves to the same asset. Useful for Storybook fixtures and snapshot tests.","parameters":[{"name":"seed","in":"path","required":true,"schema":{"type":"string"}},{"name":"width","in":"path","required":true,"schema":{"type":"integer"}},{"name":"height","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"302":{"$ref":"#/components/responses/MediaRedirect"}}}},"/photo/id/{id}/{width}/{height}":{"get":{"tags":["media"],"summary":"Specific photo by asset ID","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"width","in":"path","required":true,"schema":{"type":"integer"}},{"name":"height","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"302":{"$ref":"#/components/responses/MediaRedirect"},"404":{"description":"No asset with that id"}}}},"/video":{"get":{"tags":["media"],"summary":"Random video, default 720p","responses":{"302":{"$ref":"#/components/responses/MediaRedirect"}}}},"/video/{aspect}":{"get":{"tags":["media"],"summary":"Random video at a given aspect","description":"Aspect-bucketed pick. Falls back to all-videos when the requested bucket is empty; `X-Aspect-Fallback: 1` signals the fallback fired and `X-Aspect-Requested` echoes the original ask.","parameters":[{"name":"aspect","in":"path","required":true,"schema":{"$ref":"#/components/schemas/VideoAspect"}},{"name":"category","in":"query","schema":{"$ref":"#/components/schemas/VideoCategory"}}],"responses":{"302":{"$ref":"#/components/responses/MediaRedirect"}}}},"/video/{aspect}/{height}":{"get":{"tags":["media"],"summary":"Random video at aspect + specific rung","parameters":[{"name":"aspect","in":"path","required":true,"schema":{"$ref":"#/components/schemas/VideoAspect"}},{"name":"height","in":"path","required":true,"schema":{"type":"integer","enum":[240,360,480,720,1080]}}],"responses":{"302":{"$ref":"#/components/responses/MediaRedirect"}}}},"/video/{aspect}.m3u8":{"get":{"tags":["manifests"],"summary":"Random video as HLS master playlist","description":"Returns a 302 to the CMAF/fMP4 HLS master playlist for the picked asset. Falls back transparently to the mp4 redirect when the asset has no HLS tree (`X-HLS-Available: 0` signals the fallback). Native Safari plays the redirect target directly. In other browsers, attach hls.js, Vidstack, or Mux Player to the resolved URL.","parameters":[{"name":"aspect","in":"path","required":true,"schema":{"$ref":"#/components/schemas/VideoAspect"}}],"responses":{"302":{"description":"Redirect to master.m3u8 (or mp4 fallback)"}}}},"/video/seed/{seed}/{aspect}":{"get":{"tags":["media"],"summary":"Deterministic video by seed","parameters":[{"name":"seed","in":"path","required":true,"schema":{"type":"string"}},{"name":"aspect","in":"path","required":true,"schema":{"$ref":"#/components/schemas/VideoAspect"}}],"responses":{"302":{"$ref":"#/components/responses/MediaRedirect"}}}},"/video/id/{id}":{"get":{"tags":["media"],"summary":"Specific video by asset ID","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"302":{"$ref":"#/components/responses/MediaRedirect"},"404":{"description":"No asset with that id"}}}},"/video/id/{id}.m3u8":{"get":{"tags":["manifests"],"summary":"Specific video as HLS master playlist","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"302":{"description":"Redirect to master.m3u8"}}}},"/video/id/{id}.vtt":{"get":{"tags":["manifests"],"summary":"Single-file WEBVTT captions for a specific video","description":"Returns the auto-generated English caption track (Whisper via Cloudflare Workers AI). 404 when the asset has no detectable speech or has not yet been processed.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"302":{"description":"Redirect to en.vtt"},"404":{"description":"No captions for this asset"}}}},"/audio":{"get":{"tags":["media"],"summary":"Random ~60s audio clip as MP3","description":"Source: Internet Archive 78rpm collection (public domain). Stylistically narrow: classical, early jazz, marches.","parameters":[{"name":"category","in":"query","schema":{"$ref":"#/components/schemas/AudioCategory"}}],"responses":{"302":{"$ref":"#/components/responses/MediaRedirect"}}}},"/audio/seed/{seed}":{"get":{"tags":["media"],"summary":"Deterministic audio by seed","parameters":[{"name":"seed","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"302":{"$ref":"#/components/responses/MediaRedirect"}}}},"/audio/id/{id}":{"get":{"tags":["media"],"summary":"Specific audio by asset ID","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"302":{"$ref":"#/components/responses/MediaRedirect"}}}},"/v2/list/{type}":{"get":{"tags":["metadata"],"summary":"Paginated library listing","description":"Slim-by-default (omits `variants` and `poster_renditions` — ~80% of the per-item bytes). Pass `?include=full` to opt into the heavy fields. Rate-limited to 120 req/min per IP.","parameters":[{"name":"type","in":"path","required":true,"schema":{"type":"string","enum":["video","photo","audio"]}},{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":30}},{"name":"category","in":"query","schema":{"type":"string"}},{"name":"aspect","in":"query","schema":{"type":"string","description":"Video only."}},{"name":"include","in":"query","schema":{"type":"string","description":"Comma-separated: `variants`, `poster_renditions`, or `full`."}}],"responses":{"200":{"description":"Paginated list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v2/info/{type}/{id}":{"get":{"tags":["metadata"],"summary":"Full metadata for one asset","description":"Always returns the full shape (variants + poster_renditions + captions + hls fields). Rate-limited to 120 req/min per IP.","parameters":[{"name":"type","in":"path","required":true,"schema":{"type":"string","enum":["video","photo","audio"]}},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Asset metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetInfo"}}}},"404":{"description":"No asset with that id"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/cdn/{key}":{"get":{"tags":["cdn"],"summary":"Direct asset byte serving","description":"Final byte-serving path. Range-aware, edge-cached `immutable`, 1-year TTL. Content-Type correct for `.m3u8` (application/vnd.apple.mpegurl), `.m4s` (video/mp4), `.vtt` (text/vtt), and the underlying media types.","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","description":"Full R2 key (path)."}}],"responses":{"200":{"description":"Asset bytes"},"206":{"description":"Partial content (range request)"},"304":{"description":"Not Modified (If-None-Match)"},"404":{"description":"No such asset"}}}},"/healthz":{"get":{"tags":["metadata"],"summary":"Health check","responses":{"200":{"description":"Worker is up","content":{"text/plain":{"example":"ok"}}}}}},"/llms.txt":{"get":{"tags":["metadata"],"summary":"Short LLM-readable index of the service","responses":{"200":{"description":"text/markdown"}}}},"/llms-full.txt":{"get":{"tags":["metadata"],"summary":"Full LLM-readable docs","responses":{"200":{"description":"text/markdown"}}}}},"components":{"schemas":{"VideoAspect":{"type":"string","enum":["16x9","9x16","1x1"],"description":"Aliases accepted: landscape, portrait, square, 16:9, 9:16, 1:1."},"VideoCategory":{"type":"string","enum":["nature","people","urban","abstract","food"]},"PhotoCategory":{"type":"string","enum":["nature","people","urban","abstract","food"]},"AudioCategory":{"type":"string","enum":["ambient","electronic","classical","lofi","percussion"]},"VideoVariant":{"type":"object","properties":{"key":{"type":"string"},"width":{"type":"integer"},"height":{"type":"integer"},"bitrate_kbps":{"type":"integer"},"format":{"type":"string"},"bytes":{"type":"integer"},"hash":{"type":"string"}},"required":["key","width","height","bitrate_kbps","format","bytes"]},"HlsRung":{"type":"object","properties":{"label":{"type":"string"},"height":{"type":"integer"},"width":{"type":"integer"},"bitrate_kbps":{"type":"integer"}},"required":["label","height","width","bitrate_kbps"]},"PublicCaptionTrack":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"lang":{"type":"string"},"name":{"type":"string"},"auto":{"type":"boolean"},"format":{"type":"string","enum":["webvtt-hls","vtt"]},"bytes":{"type":"integer"}},"required":["url","lang","name","auto","format","bytes"]},"AssetInfo":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["video","photo","audio"]},"category":{"type":"string"},"aspect":{"type":["string","null"],"enum":["16x9","9x16","1x1",null]},"width":{"type":"integer"},"height":{"type":"integer"},"duration_ms":{"type":"integer"},"poster_url":{"type":["string","null"],"format":"uri"},"preview_url":{"type":["string","null"],"format":"uri"},"has_audio":{"type":["boolean","null"]},"has_captions":{"type":["boolean","null"]},"hls_url":{"type":["string","null"],"format":"uri","description":"Absolute URL to the HLS master playlist when available."},"hls_rungs":{"type":["array","null"],"items":{"$ref":"#/components/schemas/HlsRung"}},"captions":{"type":["array","null"],"items":{"$ref":"#/components/schemas/PublicCaptionTrack"}},"variants":{"type":"array","items":{"$ref":"#/components/schemas/VideoVariant"}},"attribution":{"type":"object","properties":{"source":{"type":"string"},"source_url":{"type":"string","format":"uri"},"license":{"type":"string"},"author":{"type":["string","null"]},"author_url":{"type":["string","null"],"format":"uri"}},"required":["source","source_url","license"]},"added_at":{"type":"integer"}},"required":["id","type","category","width","height","duration_ms","attribution"]},"ListResponse":{"type":"object","properties":{"_meta":{"type":"object","properties":{"service":{"type":"string"},"description":{"type":"string"},"operator":{"type":"string"},"production_hosting":{"type":"string","format":"uri"},"docs":{"type":"string","format":"uri"}}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"},"items":{"type":"array","items":{"$ref":"#/components/schemas/AssetInfo"}}},"required":["page","limit","total","pages","items"]},"Error":{"type":"object","properties":{"error":{"type":"string"},"hint":{"type":"string"},"valid":{"type":"array","items":{"type":"string"}}},"required":["error"]}},"responses":{"MediaRedirect":{"description":"302 redirect to a `/cdn/<key>` URL. Headers include `X-Asset-Id`, `X-Source`, `X-Attribution`, `X-Source-Url`, and (for video) `X-Aspect`.","headers":{"X-Asset-Id":{"schema":{"type":"string"}},"X-Source":{"schema":{"type":"string"}},"X-Attribution":{"schema":{"type":"string"}},"X-Source-Url":{"schema":{"type":"string","format":"uri"}}}},"BadRequest":{"description":"Invalid path or query parameters","content":{"text/plain":{"example":"Invalid /photo path. Expected: ..."},"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests — backoff per `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}},"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}}}}}}}