API Reference
Frames
The storyboard in a job's results, and how to fetch its sheets.
A brands or objects job with return_proof on (the default) comes back with a storyboard in results: frames we
analyzed, tiled into JPEG sheets, so you can show where a brand or an object was. On a brands job that is up to 150
frames spread across the video.
GET /v1/frames/:key
Returns one storyboard sheet.
curl https://api.netraflow.com/v1/frames/storyboard/job_abc123/sheet_0.jpg \
-H "X-Api-Key: sk_live_your_key_here" \
-o sheet_0.jpgHTTP/1.1 200 OK
Content-Type: image/jpeg
Cache-Control: private, max-age=31536000, immutable
<JPEG bytes>- Where the key comes from. Each entry of
results.storyboard.sheetsis already the whole path, such as/v1/frames/storyboard/job_abc123/sheet_0.jpg. Request it as it is, afterhttps://api.netraflow.com, and don't URL-encode its slashes. - Auth. The same
X-Api-Keyheader as every request. The key needs thejobs:readscope. - Response. HTTP 200 with the image itself,
Content-Type: image/jpeg. - Caching. A sheet never changes once it is written, so it is sent with
Cache-Control: private, max-age=31536000, immutable: keep it as long as you like. - How long it lasts. As long as the job's results: a completed job keeps its storyboard until the workspace is deleted. A failed or cancelled job has none.
- Errors.
NOT_FOUND(404) when the key is not a sheet of a job in your workspace, or the sheet does not exist. The body has the same{ error, meta }shape as every other error.
Storyboard
"storyboard": {
"version": 2,
"interval_ms": 1000,
"timestamps_ms": [500, 1500, 2500, 3500],
"tile": { "w": 580, "h": 326 },
"grid": { "cols": 8, "rows": 8 },
"count": 4,
"duration_ms": 4000,
"sheets": ["/v1/frames/storyboard/job_abc123/sheet_0.jpg"]
}| Prop | Type | Description |
|---|---|---|
| version | 1 | 2 | How a tile relates to its timestamp. 1: the tile covers from its own timestamp to the next tile's. 2: the timestamp is the middle of the sampled interval, so the tile spans halfway to each neighbour. |
| interval_ms | integer | Typical spacing between tiles, in milliseconds. |
| timestamps_ms | integer[] (optional) | True timestamp of each tile in milliseconds, ascending, one per tile. Frames are analyzed non-uniformly, so prefer this over interval_ms when present. Absent only on older results, where tile k sits at k × interval_ms. |
| tile | { w: integer, h: integer } | Size of one tile in pixels. The longer side is 580 and the shape follows the video's. |
| grid | { cols: integer, rows: integer } | Tiles per row and rows per sheet (8 × 8 today). Tile k is on sheet floor(k / (cols × rows)), row-major within it. |
| count | integer | Total tiles across all sheets. The last sheet can be partly empty (black). |
| duration_ms | number | Video duration in milliseconds. |
| sheets | string[] | Path of each sheet, in order, to fetch with GET /v1/frames/:key. |
The storyboard is the one place the API reports milliseconds. Every other timestamp in a result is in seconds.
The tiles are plain frames with nothing drawn on them. To show where something was, find the tile nearest a detection's
timestamp and draw its box over that tile yourself: brands carry theirs in frame_detections, objects in frames.