NetraFlow
Capabilities

Brands

Detect brand appearances in video with confidence scores, on-screen intervals, and visual evidence.

Brand detection finds brands three ways: visible on screen, mentioned in speech, and named in the video's own metadata (title, description, tags). Each brand comes back with a confidence score and a list of appearances.

On the Free and Starter plans, a brands job must be targeted — pass brands (names to look for), surfaces (where to look), or both. An untargeted brands job is rejected with PLAN_REQUIRED (403). Pro and Scale can run open-ended detection.

curl -X POST https://api.netraflow.com/v1/jobs \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: sk_live_your_key_here" \
  -d '{
    "url": "https://www.youtube.com/watch?v=example",
    "capabilities": ["brands"],
    "brands": ["Nike", "Adidas"]
  }'
{
  "data": {
    "job_id": "job_abc123",
    "status": "completed",
    "results": {
      "brands": [
        {
          "name": "nike",
          "raw_name": "Nike",
          "confidence": 0.95,
          "total_appearances": 3,
          "total_visible_duration": 8.4,
          "first_seen": 12.5,
          "last_seen": 145.0,
          "appearances": [
            {
              "timestamp": 12.5,
              "timestamp_start": 12.5,
              "timestamp_end": 16.0,
              "visible_duration": 3.5,
              "confidence": 0.93,
              "verified": true,
              "source": "visual",
              "bounding_box": { "x": 0.3, "y": 0.2, "width": 0.15, "height": 0.1 }
            },
            {
              "timestamp": 89.0,
              "timestamp_start": 89.0,
              "timestamp_end": 89.6,
              "confidence": 0.88,
              "source": "audio",
              "context": "Mentioned in speech",
              "speech_context": "We partnered with Nike for this campaign."
            },
            {
              "source": "metadata",
              "confidence": 0.5,
              "context": "Mentioned in video metadata"
            }
          ]
        }
      ],
      "confidence_summary": { "high": 1, "medium": 0, "low": 0, "total": 1 }
    }
  }
}

Targeting

Two optional request fields narrow the search. Both are recommended even where they aren't required — a targeted job is faster and more accurate than open-ended detection.

PropTypeDescription
brandsstring[]Brand names to look for. Max 50 names, 100 characters each.
surfacesstring[]Where the brand should appear, as surface slugs (e.g. "jersey"). Max 10. An unknown or unavailable slug is rejected with INVALID_SURFACE (422).

When you pass surfaces, each kept appearance carries the surface it was found on, and each brand gets a surfaces rollup of the distinct surfaces it appeared on. This is what answers a find {brand} on {surface} question.

Brand fields

PropTypeDescription
namestringCanonical brand identity, always lowercase ("nike"). Stable across runs and across the sources that found the brand, so it is what to key on — not what to display.
raw_namestringThe human-readable label to render ("Nike", "AT&T", "npm"). Always present on new results; older results may omit it, in which case fall back to `name`.
confidencenumber (0-1)Overall confidence for this brand.
low_confidenceboolean (optional)True when the detection sits below the high-confidence band — treat it as a candidate.
total_appearancesintegerNumber of distinct appearances: on-screen intervals plus speech and metadata mentions. Not a count of frames.
total_visible_durationnumber (optional)Combined seconds the brand was on screen. Derived from visual appearances only.
first_seennumber (optional)Seconds. First timed appearance. Absent when the brand was only found in metadata.
last_seennumber (optional)Seconds. Last timed appearance.
surfacesstring[] (optional)Distinct surfaces this brand appeared on. Present only on surface-targeted jobs.
appearancesAppearance[]The individual appearances.

Appearance fields

Appearances are not uniform — branch on source first. A metadata appearance is timeless: it carries no timestamp, no window, no duration, and no box, because a mention in a video's title isn't tied to a moment.

PropTypeDescription
source"visual" | "audio" | "metadata"How the brand was found: on screen, in speech, or in the video's title/description/tags.
timestampnumber (optional)Seconds. Start of the appearance. Absent on metadata appearances.
timestamp_startnumber (optional)Seconds. Start of the interval.
timestamp_endnumber (optional)Seconds. End of the interval.
visible_durationnumber (optional)Seconds the brand was on screen for this interval. Frame-coverage based: a detection on a static shot covers the stable stretch up to the next analyzed frame, so a single detection can yield several seconds.
confidencenumber (0-1, optional)Confidence for this individual appearance, distinct from the brand-level score.
verifiedboolean (optional)Set on visual appearances that completed brand resolution.
bounding_box{ x, y, width, height } (optional)Normalized 0-1 coordinates. One representative box for the whole interval.
frame_detectionsFrameDetection[] (optional)Per-frame boxes across the interval, so a box can track the logo as it moves. Visual only.
surfacestring (optional)The surface the brand was found on. Present only on surface-targeted jobs.
contextstring (optional)Short fixed label on audio and metadata appearances ("Mentioned in speech"). Not emitted on visual appearances.
speech_contextstring (optional)Transcript excerpt around an audio mention. Requires return_proof.

Frame detection fields

PropTypeDescription
timestampnumberSeconds. The analyzed frame this box came from.
bounding_box{ x, y, width, height }Normalized 0-1 coordinates of the brand in that frame.
confidencenumber (0-1, optional)Score for this box.
confidence_kind"detector" | "match" (optional)How to read confidence. "detector" (or absent) is a recognition score. "match" is a visual-similarity score rather than a recognition score — a low value there does not mean the detection is wrong.
mask{ size, counts } (optional)Run-length silhouette of the surface region the brand sits on, for overlay rendering. Surface-targeted detections only.

Visual evidence

return_proof is on by default. On brands jobs it adds a storyboard to results: the analyzed frames composited into tiled sheets, which — combined with frame_detections — lets you show the exact frame a brand was detected in, with the box drawn on it. Sheets are fetched through GET /v1/frames/{key} using the same X-Api-Key header.

return_proof also controls whether audio appearances carry speech_context transcript excerpts. Set return_proof: false to skip both and reduce response size.

PropTypeDescription
interval_msintegerNominal spacing between tiles, in milliseconds.
timestamps_msinteger[] (optional)True timestamp of each tile, ascending, one per tile. Frames are analyzed non-uniformly, so prefer this over interval_ms when present.
tile{ w, h }Tile dimensions in pixels.
grid{ cols, rows }Tile layout per sheet. Tile k is on sheet floor(k / (cols * rows)), row-major within it.
countintegerTotal tiles across all sheets.
duration_msnumberVideo duration in milliseconds.
sheetsstring[]Sheet keys to fetch via GET /v1/frames/{key}.

The storyboard manifest is the one place the API reports milliseconds. Every other timestamp in a result is in seconds.

Result-level signals

Brands jobs also populate two top-level fields alongside results.brands:

PropTypeDescription
confidence_summary{ high, medium, low, total }Detection counts bucketed by confidence band — high >= 0.8, low < 0.5, medium in between.
meta.brand_detection_degradedboolean (optional)True when the visual detection stage ran degraded and results may be incomplete. Check this before treating an empty result as "no brands present".

Duration limits

Brands jobs analyze frames, so they use your plan's standard video ceiling: 1 minute on Free, 3 on Starter, 10 on Pro, 20 on Scale. A longer video fails with VIDEO_TOO_LONG after ingestion.

On this page