Bitrail

Home/Docs/API

Machine-readable catalogue

One document, no versioned endpoints, no key. If your job currently scrapes the HTML, read this instead.

/api/streams.json
/health.txt
/media/SHA256SUMS

Shape

{
  "version": 2,
  "updated": "2026-08-12",
  "renditions": [
    { "label": "720p", "width": 1280, "height": 720,
      "video_kbps": 2500, "audio_kbps": 128 }
  ],
  "streams": [
    {
      "id": "timecode",
      "title": "Timecode and colour bars",
      "fps": 30,
      "duration_s": 60,
      "progressive": { "720p": "/media/timecode/timecode-720p.mp4" },
      "hls": "/media/timecode/hls/master.m3u8"
    }
  ]
}
versionIncrements only when a field is removed or changes meaning. Adding a field does not bump it.
idStable. An id is never reused for different content.
progressiveMap of rendition label to path. Not every stream has every rendition.
hlsPath to the multivariant playlist, or null.
PathsRoot-relative. Prefix with the origin you fetched the document from.

Examples

Every 1080p progressive URL:

curl -s https://vid.thisaintu.sbs/api/streams.json \
  | jq -r '.streams[].progressive["1080p"] // empty'

Only the sources that ship an HLS ladder:

curl -s https://vid.thisaintu.sbs/api/streams.json \
  | jq -r '.streams[] | select(.hls) | "\(.id)\t\(.hls)"'

Fail a CI job if a stream you depend on disappears:

curl -s https://vid.thisaintu.sbs/api/streams.json \
  | jq -e '.streams[] | select(.id=="motion")' >/dev/null

Health

/health.txt returns three bytes and is served with no-store. Use it to distinguish an outage from a content problem: if it answers and a media URL does not, the origin is up and the asset is the issue.

There is no write API and there will not be one. Everything here is static files behind a cache, which is the reason it stays up while costing nothing to run.