Screenshots
Screenshots are stored as discrete, content-addressed (sha-256) PNG artifacts, separate from the run report. All routes require client credentials and are scoped to the authenticated repository.
GET /api/v1/runs/:id/screenshots/:artifactId
Fetch one offloaded screenshot as a image/png body. artifactId is the sha-256 id from a result's screenshotRefs. Scoped to the run's repository; returns 404 for an unknown id and 400 for a malformed one. Responses are immutable (content-addressed), so they carry a long-lived Cache-Control.
http
200 OK
Content-Type: image/png
<binary PNG>Uploading screenshots ahead of a run
dungbeetle push uploads screenshots as discrete, content-addressed artifacts so the run POST body stays small and unchanged images transfer zero bytes. (Sending them inline under result.screenshot still works — the server offloads those on ingest.) The flow:
POST /api/v1/screenshots/probewith{ "digests": ["<sha256>", …] }→{ "missing": ["<sha256>", …] }— the subset this repository doesn't have yet.PUT /api/v1/screenshots/:digestwith the raw PNG body for each missing digest. Idempotent: a digest already stored returns200 {id, deduped:true}, a new one201 {id, deduped:false}. The body must hash to:digest(else400); artifacts count toward the storage quota (402when over a hard limit).POST /api/v1/runswith each result carryingscreenshotRefs(the digests) instead ofscreenshot. Refs pointing at artifacts the server doesn't have are dropped from the stored report.