testsrc

API reference

The baseline catalog is public. Files and full fact sheets need a token. Everything is plain HTTPS and JSON, so any test runner, script or agent can use it.

Base URLhttps://testsrc.com/v1

The API is in early access. Ask for a token: free for open-source projects, $99/month per organisation for companies.

Basics

Tokens
Send Authorization: Bearer tsk_.... Create and revoke tokens on your account, one per place they run, and keep them in a CI secret.
Snapshots
Every file belongs to a snapshot named by date. Add ?snapshot=2026-11-02 to pin one: the same snapshot always returns the same bytes. Without it you get the latest.
Browsers and players
CORS and range requests are on, so a web player or a test page can fetch files directly.

The file, then its facts, pinned to a snapshot

curl -H "Authorization: Bearer $TESTSRC_TOKEN" -O \
  "https://testsrc.com/v1/files/codec/hevc-aac.mp4?snapshot=2026-11-02"
curl -H "Authorization: Bearer $TESTSRC_TOKEN" \
  "https://testsrc.com/v1/cases/codec/hevc-aac.mp4/facts?snapshot=2026-11-02"

Endpoints

GET/v1/catalog Public

The cases in the snapshot: each one's id, layer (1 for baseline files, 2 for edge cases), expected outcome, size in bytes, and the files it consists of. Streaming cases list their playlist and segments.

Without a token it lists the baseline files and the edge cases described on testsrc.com/cases, and says how many more there are; with a token, every case.

ParameterInDescription
snapshotqueryOptional. A snapshot name; the latest if left out.
AuthorizationheaderOptional. With a token, the catalog lists every case.

Request

curl -H "Authorization: Bearer $TESTSRC_TOKEN" https://testsrc.com/v1/catalog

Response

{
  "snapshot": "2026-11-02",
  "count": 163,
  "cases": [
    {
      "id": "codec/av1-aac.mp4",
      "layer": 1,
      "outcome": "must-play",
      "size_bytes": 3602413,
      "files": ["av1-aac.mp4"]
    },
    {
      "id": "hls/ts.m3u8",
      "layer": 1,
      "outcome": "must-play",
      "size_bytes": 5616913,
      "files": ["ts.m3u8", "ts_000.ts", "ts_001.ts", "ts_002.ts"]
    },
    …
  ]
}
GET/v1/snapshots Public

The snapshot names and which one is the latest.

Request

curl https://testsrc.com/v1/snapshots

Response

{ "latest": "2026-11-02", "snapshots": ["2026-10-29", "2026-11-02"] }
GET/v1/cases/{id} Public

What a case is. Baseline cases come with their full fact sheet and recipe; edge cases with headline facts. Edge cases that aren't on testsrc.com/cases answer only with a token.

ParameterInDescription
idpathThe case id from the catalog, like edge/rotation-90-display-matrix.mp4.
snapshotqueryOptional.

Request

curl https://testsrc.com/v1/cases/edge/rotation-90-display-matrix.mp4

Response

{
  "id": "edge/rotation-90-display-matrix.mp4",
  "layer": 2,
  "why": null,
  "files": ["rotation-90-display-matrix.mp4"],
  "size_bytes": 5532359,
  "verified_with": {
    "generator": "gen v0.2",
    "ffmpeg": "7.1.5-0+deb13u1",
    "gstreamer": "1.26.2",
    "image": "sha256:c74db3c8f454"
  },
  "container": { "format": "mov,mp4,m4a,3gp,3g2,mj2", "duration_s": 6 },
  "video": { "codec": "h264", "width": 1920, "height": 1080, "fps": "30" },
  "audio": [{ "codec": "aac", "channels": 2, "sample_rate": 48000 }],
  "more": "Full facts, exact parameters and the expected outcome: GET /v1/cases/{id}/facts with a token."
}
GET/v1/cases/{id}/facts Token

The full fact sheet: container layout, every measured value, keyframes, the expected outcome and what a test can assert, with tolerances, and per-frame decode checksums where the codec allows them.

ParameterInDescription
idpathThe case id.
snapshotqueryOptional.

Request

curl -H "Authorization: Bearer $TESTSRC_TOKEN" \
  https://testsrc.com/v1/cases/codec/av1-aac.mp4/facts

Response

{
  "id": "codec/av1-aac.mp4",
  "layer": 1,
  …,
  "expect": {
    "outcome": "must-play",
    "duration_s": 6,
    "duration_tol_s": 0.15,
    "frames": 180,
    "first_code": 0,
    "fps": 30,
    "display_aspect": "16:9",
    "orientation": "none",
    "colour": { "matrix": "bt709", "range": "limited", "tol": 8 },
    "max_log_errors": 0,
    "exact_seek": false,
    "beep_every_frames": 30,
    "av_offset_ms": 0,
    "av_tol_ms": 20
  },
  "gated": {
    "frame_md5": {
      "decoder_output": "yuv420p",
      "frames": [
        "a4d1b7fa8d7a711139129a8c9378c17f",
        "2a31ab08c8a1aafe2da7376f75803647",
        …
      ]
    }
  }
}
GETHEAD/v1/files/{path} Token

A test file, or a playlist or segment of a streaming case. Files never change within a snapshot, so they're served with an ETag and cached as immutable. A trial token counts each case once, whichever of its files it fetches.

ParameterInDescription
pathpathA case id, or a file next to it from the catalog's files, like hls/ts_001.ts.
RangeheaderOptional. bytes=0-1023, open-ended and suffix ranges answer 206.
snapshotqueryOptional.

Request

curl -H "Authorization: Bearer $TESTSRC_TOKEN" -r 0-1023 -D - -o /dev/null \
  https://testsrc.com/v1/files/codec/av1-aac.mp4

Response headers

HTTP/2 206
content-type: video/mp4
content-range: bytes 0-1023/3602413
content-length: 1024
accept-ranges: bytes
cache-control: private, max-age=86400, immutable
x-testsrc-snapshot: 2026-11-02

Players that can send a header play HLS and DASH cases straight from the API:

ffmpeg -headers "Authorization: Bearer $TESTSRC_TOKEN"$'\r\n' \
  -i https://testsrc.com/v1/files/hls/ts.m3u8 -f null -
GET/v1/usage Token

What the token used today (UTC), its limits and when they reset. Doesn't count against the quota.

Request

curl -H "Authorization: Bearer $TESTSRC_TOKEN" https://testsrc.com/v1/usage
FieldDescription
tokenThe token's id, like t_1a2b3c4d5e. The token itself is never echoed.
planoss, company or trial.
dayThe UTC day the counts are for.
used.requests, used.bytesRequests and bytes served today.
limits.requests_per_day, limits.bytes_per_dayThe daily quota.
limits.distinct_casesHow many different cases the token may fetch: a number for trial tokens, null otherwise.
resets_in_sSeconds until 00:00 UTC.

Limits

Requests are limited per minute and per UTC day, in requests and in bytes; /v1/usage shows where a token stands. A trial token can fetch 30 different cases; the full catalog opens after the first payment. When a limit is hit, the response says which one and when it resets.

Errors

Errors are JSON with a message for people and a stable code for programs:

{
  "error": "Daily quota used up. It resets at 00:00 UTC. See GET /v1/usage.",
  "code": "quota"
}
StatusCodeMeaning
400bad_snapshotThe snapshot isn't a date like 2026-11-02.
401no_tokenNo Authorization header.
401bad_tokenUnknown, malformed or revoked token.
403trial_limitThe trial token has fetched its 30 cases.
404no_case, no_file, no_snapshotNot in that snapshot.
405method_not_allowedOnly GET and HEAD (and CORS preflight) are served.
429rate_limitedToo many requests this minute. Retry after Retry-After seconds.
429quotaDaily quota used up. It resets at 00:00 UTC; Retry-After says when.