HyperFrames check via the Sume API: caption collisions pre-render

Send check with caption_zone to POST /v1/hyperframes-previews and get findings, contrast and overlap reports. A failing check is still a completed job.

4 min readSume
All posts

To catch a caption collision before you render, add a check object to POST /v1/hyperframes-previews and set caption_zone to the band where captions will sit. Sume then runs the vendor hyperframes check in Chromium instead of taking stills, and the finished resource carries a check report with ok, errors, warnings and a list of findings.

The details here come from the live Sume OpenAPI document (read 2026-10-10). Reading the report correctly has one trap: the job completes even when the check finds errors.

What does the check run?

The schema description says the check covers runtime errors, layout overflow, overlap and occlusion, WCAG contrast, *.motion.json assertions, and, when you give caption_zone, collisions with the caption band.

The check object accepts these keys, all optional.

check options (OpenAPI, read 2026-10-10)
KeyType and rangeEffect
at1 to 6 numbersTimes to inspect.
samplesinteger 1 to 60How many sample points to take.
caption_zonestring, up to 200 characters, digits, letters and . , ; = % : -A band such as x0=0;y0=.82;x1=1;y1=1;severity=error.
snapshotsboolean, default trueAdds overview frames and per-finding crops.
strictbooleanWarnings fail the report too.

Why is a failed check still a completed job?

The OpenAPI text is explicit: the job completes with a report even when the check finds errors, because the CLI's exit code 1 means findings, not a failure. So status: completed tells you the check ran. It does not tell you the composition is clean.

Your gate must read check.ok and the findings. A job that failed is different: that means the check itself could not run, and error on the resource explains why.

  • check.ok false: block the render.
  • check.errors and check.warnings: counts you can log.
  • findings[]: each has section, severity, code, message, and sometimes selector, fixHint and time.
  • images[]: overview and per-finding PNGs, each with kind, t, url and filename.

How do I turn it into a CI gate?

Submit with mode: async, poll the resource until status is terminal, then apply a pure function to the report. The helper below assumes you already fetched the resource with the same call function as in the stills post. It exits non-zero on any error-severity finding, and also when ok is false.

Keep the gate separate from the poll loop so you can unit test it with a saved report.

import json, os, urllib.request

def call(method, path, body=None):
    req = urllib.request.Request(
        "https://api.sume.com" + path, method=method,
        data=json.dumps(body).encode() if body else None,
        headers={"x-api-key": os.environ["SUME_API_KEY"], "User-Agent": "sume-example/1.0",
                 "Content-Type": "application/json"})
    with urllib.request.urlopen(req, timeout=30) as r:
        return json.load(r)["data"]

def gate(preview):
    check = preview.get("check")
    if check is None:
        raise SystemExit("not a check job")
    errors = [f for f in check["findings"] if f["severity"] == "error"]
    for f in errors:
        print(f["code"], f["message"])
    raise SystemExit(1 if errors or not check["ok"] else 0)

What does a findings row look like in practice?

Each finding names a section (for example layout or contrast), a severity, a stable code, a human message, and optionally a CSS selector pointing at the offending element, a fixHint, and a time in seconds. The stable code is the field to key your own suppressions on; messages are written for people and can change.

A sensible policy is to fail the build on error severity, annotate the pull request with warning rows, and keep a small allowlist of codes your brand template triggers on purpose. Store the allowlist next to the composition so a reviewer can see why a finding is ignored.

The images array lets you attach evidence. overview frames show the whole composition at the sampled times, and finding crops zoom on the element a finding names. Because they are media.sume.com artifacts, you can link them from a review comment without re-hosting.

What should I watch for?

strict: true turns warnings into failures, which is useful for release branches and noisy on drafts. Pair it with snapshots left on so a reviewer sees the crops.

Because the check is a separate compute job, treat repeated submits as spend and cache by the html_sha256 you already compute. Read the cost on the usage page instead of guessing.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume