Frameloft

Delivery API

Everything a player needs is one path shape and one token. This page documents what our edges answer, so you can tell a real failure from a bot hitting an expired link.

Base

https://frameloft.online/static/getFile/

Segments and their sessions live under this prefix. It is the only prefix our edges proxy; anything else on the host is the marketing site or a 404.

Segment path

/static/getFile/video/<class>.ts/<session>

<class> names the rendition inside the asset, <session> is the 48-character token your backend was handed. The .ts suffix is part of the class name, not a file on disk — it keeps players and proxies that sniff extensions happy.

ClassCarriesTypical size
preview.tsLowest rendition, served first so playback starts while the ladder warms up0.4–1.5 MB
part.tsMain rendition segments, the bulk of every view1–6 MB
frame.tsKeyframe-aligned segment used for seeks and scrub previews0.2–2 MB
clip.tsTrimmed export of a range, generated on demand1–8 MB
thumb.tsThumbnail strip for the timeline40–300 KB
cover.tsPoster and social preview still20–150 KB

Classes are fixed. A request for a class an asset does not have is a 404, not an empty success.

Sessions

A session token is 48 hex-ish characters, issued per viewer and asset, and accepted for a short window. Nothing about it is secret on the client — it is simply useless elsewhere:

Tokens are issued by the console or by your server key. There is no public endpoint that mints them, which is why crawlers only ever see 400.

Requests we accept

RuleAnswer when broken
GET and HEAD only405 Method Not Allowed
No request body on delivery paths403 Forbidden
Request line and headers under 64 KB413 Payload Too Large
One asset per session400 Bad Request, empty body
128 open streams per session, 4 000 per edge503 with Retry-After
A single segment stream may run 300 sconnection closed after the limit

Status codes in full

CodeMeaning
200Segment follows, video/mp2t.
206Range served. Seeks and resumes use this; we do not re-pull the whole segment.
400Session expired, malformed, or issued for another asset. Body is empty on purpose.
403A body or an unsupported verb arrived on a delivery path.
404Unknown class, unknown asset, or a path outside the delivery prefix.
405Method other than GET or HEAD.
503Concurrency limit reached. Back off and retry; the edge is healthy.

Player snippet

// hls.js, the manifest your backend rendered for this session
const hls = new Hls({ maxBufferLength: 20, enableWorker: true });
hls.loadSource(`https://frameloft.online/m/${assetId}/${session}.m3u8`);
hls.attachMedia(video);

hls.on(Hls.Events.ERROR, (_, data) => {
  // 400 here means the session died mid-view: ask your backend for a new one
  if (data.response && data.response.code === 400) renewSession();
});

Native players (Safari, AVPlayer, ExoPlayer) need no special handling: hand them the same manifest URL and they will walk the same segment paths.

Caching

Segments are immutable for the life of a rendition, so edges keep them until you replace the asset. Manifests and the marketing pages are not cached. We send no Set-Cookie and ignore query strings, so a cache key is just the path.

Changelog