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.

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.
| Key | Type and range | Effect |
|---|---|---|
| at | 1 to 6 numbers | Times to inspect. |
| samples | integer 1 to 60 | How many sample points to take. |
| caption_zone | string, up to 200 characters, digits, letters and . , ; = % : - | A band such as x0=0;y0=.82;x1=1;y1=1;severity=error. |
| snapshots | boolean, default true | Adds overview frames and per-finding crops. |
| strict | boolean | Warnings 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.okfalse: block the render.check.errorsandcheck.warnings: counts you can log.findings[]: each hassection,severity,code,message, and sometimesselector,fixHintandtime.images[]: overview and per-finding PNGs, each withkind,t,urlandfilename.
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
- image_not_fetchable on a Sume image edit: reference URL checklist
A Sume image edit failed with image_not_fetchable or input_media_unreachable. What the docs say the error means and a checklist for the reference URL.
- Image API returned 202, not an image: one Python handler for both
POST /v1/images waits 30 seconds, then returns a 202 job envelope. A Python handler that reads the status code, polls the job and returns image URLs either way.
- ky retry on POST for Sume: Idempotency-Key, 40 s timeout, v2 baseUrl
ky does not retry POST by default and times out at 10 s, but Sume sync can hold 30 s. A tested ky v2 config with a stable Idempotency-Key and no 429 retries.
- Launch-week 503 provider_capacity_exceeded: safe video submit retries
New video models cause capacity spikes. Retry 429 and 503 on Sume with the same Idempotency-Key, honor retry-after, never retry 402. Python sample included.
Written by Sume