long form
packaging

One find, every field

One result of a long or packaging run with every field. find_id comes from a run's finds. Free. MCP: get_find.

get/v1/finds/{find_id}

Request

  • Base URL: https://api.hookdetector.com (the document declares no server; this is the origin it was published from)
  • URL: https://api.hookdetector.com/v1/finds/{find_id}
  • Auth: none declared

Path parameters

find_idstring uuid required

Headers

authorizationstring nullable

Bearer hd_... from POST /v1/accounts or POST /v1/keys

Response

Successful Response

find_idstring uuid

the id to keep, reject or read it by; absent on an item of progress.items

run_idstring uuid

the run that found it

kind'long' | 'packaging'

long or packaging

rankinteger

its place in the run, from 1: the strongest outlier first

verdict'keep' | 'reject' | 'null' nullable

keep, reject or null

video_idstring

the YouTube video id

platformstring

always "youtube"

titlestring

the video's title as YouTube shows it, word for word (runs of spaces read as one)

channelstring nullable

the channel's name

channel_handlestring nullable

the channel's @handle, without the @

watch_urlstring

where to watch it

player_urlstring

an iframe src that plays it (16:9)

thumbnail_urlstring

the video's thumbnail on YouTube's image host; thumbnail_urls lists every size, best first, and a size a video lacks answers 404

viewsinteger

views when the run read it

likesinteger nullable

likes, when YouTube gave them

commentsinteger nullable

comments, when YouTube gave them

age_daysnumber nullable

days since it was posted, when the run read it

views_per_daynumber nullable

views divided by age_days

baseline_videosinteger nullable

how many recent uploads the channel's usual was measured on

found_bystring nullable

the search that surfaced it

duration_sinteger nullable

length in seconds; always over 180

posted_atstring nullable

when it was posted (ISO 8601). Exact when posted_exact is true; otherwise the latest it can be, from YouTube's "3 months ago", and never before 2023 either way

posted_exactboolean

whether posted_at is the real timestamp

channel_median_viewsinteger nullable

the channel's usual: the median views of its recent long-form uploads

outliernumber nullable

views divided by channel_median_views: 28.2 means 28 times what this channel normally gets

outlier_scoreinteger

the video on one fixed scale, 0 to 100: the outlier, its reach, how fresh it is and how hard its viewers reacted, placed between two fixed anchors. Nothing else a run found moves it, so finds from different runs rank together; it moves only with the video's own numbers and age

channel_size'small' | 'medium' | 'large' | 'null' nullable

the channel by what its uploads usually get (channel_median_views): small, medium or large

seen_beforeboolean

true when an earlier run of yours on this tab already found this video; a keep or reject made then is already on it

analysis_from_earlier_readboolean

true when the opening or the package analysis is the one an earlier run of yours wrote for this video; the numbers are this run's

channel_idstring nullable

the channel's YouTube id (UC...)

thumbnail_urlsstring[]

every thumbnail size, best first; a size a video lacks answers 404

scorenumber nullable

the ranking score outlier_score is scaled from

hook_linesinteger

long: how many lines of intro the hook reaches, counted from line 1; the last may be only partly the hook, hook_words counts exactly

hook_end_snumber

long: the second the hook ends, to a tenth, never null. Inside a line it is estimated at the opening's own pace

hook_start_snumber

long: the second the hook starts: 0 or close to it, later when a sponsor read or a greeting came first

hook_wordsinteger

long: the hook's length in words

auto_captionsboolean

long: true when the opening carries almost no punctuation (auto captions): its sentences are not marked and names may be misheard

about_subject'yes' | 'partly' | 'null' nullable

long: whether the video is about the run's subject, read from its title and opening in the call that analyses it: yes, or partly (the subject is one part of it, or it covers a neighbouring subject). Null when the question was not asked (a channel or video link) or not answered. A video the model answers "no" for is never delivered

hook_type_otherstring nullable

long: the device in words when hook_type is "other"

title_device_otherstring nullable

packaging: the device in words when title_device is "other"

outlier_tier'outlier' | 'strong' | 'breakout' | 'null' nullable

outlier (under 5 times the channel's usual), strong (5 to 10) or breakout (10 or more)

likes_per_1knumber nullable

likes for every 1,000 views

comments_per_1knumber nullable

comments for every 1,000 views

style_matchboolean nullable

when the request asked for a kind of opening or title: whether this one is that kind. Null when it asked for none

anglestring nullable

the specific angle the video takes on the subject

formatstring nullable

long: the kind of video, one of talking_head, voiceover, vlog, tutorial, interview, documentary, challenge, review, story, other

opens_withstring nullable

long: how the first seconds begin, one of cold_open, greeting, teaser, question, sponsor, other

thumbnail_checkedboolean

packaging: true when thumbnail_url is the size YouTube really served and the analysis looked at

thumbnail_sha256string

packaging: a digest of the picture the analysis looked at; a later run reuses the analysis only while YouTube serves the same picture

analysed_atstring

packaging: when the thumbnail was looked at (ISO 8601); a reused analysis keeps its own date

title_charsinteger

packaging: the title's length in characters

cut_on_phoneboolean

packaging: true when the title is longer than 60 characters, where a phone roughly cuts a title. Approximate: YouTube publishes no limit, and the cut moves with the screen, the font and the letters (about 58 to 62)

thumbnail_text_rolestring nullable

packaging: how the words on the thumbnail stand to the title, one of repeats_title, adds_to_title, contrasts_title, no_text. Counted in code from title_overlap where that can be (repeats_title at 0.7 or more, adds_to_title under 0.3); between, the model's reading

title_overlapnumber nullable

packaging: the share of the thumbnail's words that are also in the title, 0 to 1, counted in code. null when the thumbnail has no words, or its words are in a script the title does not use

on_subject'yes' | 'partly' | 'no' | 'null' nullable

packaging: whether the look, told the run's subject, judged the package to be about it: yes, or partly (it covers the subject as one part of something broader). A package judged no is never delivered. null when the run was on a channel's or a video's address, when the look gave no usable verdict, or when the analysis is one an earlier run wrote (its subject may have been another)

thumbnail_facesinteger nullable

packaging: how many faces the thumbnail shows

thumbnail_colorsstring nullable

packaging: the colours that carry the frame

whystring nullable

one line naming the outlier in words

languagestring nullable

the language spoken, as YouTube names the caption track

analysedboolean

false when the model could not analyse it: the find is still real, its analysis fields are null

hookstring

long: the hook, verbatim: the lines of intro the analysis marks as the hook, cut at the last sentence end that keeps it inside 25 seconds and 60 words, a leading sponsor read or greeting left out. The whole opening is intro_text

hook_secondsnumber nullable

long: the second the hook ends; the same number as hook_end_s, kept for older readers

introobject[]

long: the opening as it was said, cut by the transcript's own clock: lines of n (from 1), t (start second, null when the transcript had no clock) and text

intro_textstring

long: the same words as one string

intro_secondsinteger

long: how much of the opening was read

hook_typestring nullable

long: since 2026-10-02: the device the opening uses, one of curiosity_gap, contrarian_claim, specific_number, identity_callout, stakes_threat, promise_payoff, pattern_interrupt, story_open, question, direct_command, other (then hook_type_other names it in two to five words). Null on older hooks and when the write-up gave none. A client should treat an unknown value as other.

mechanismstring nullable

long: why the opening holds a viewer, quoting it word for word

promisestring nullable

what the viewer is told they will get

open_loopstring nullable

long: the question the opening leaves unanswered

title_linkstring nullable

long: how the first lines pay off the title

beatsobject[]

long: the opening in consecutive parts: from and to (line numbers of intro), beat (one of hook, stakes, proof, credibility, context, promise, preview, story, payoff, cta, other) and does

templatestring nullable

long: the hook as a fill-in structure with {placeholders}

steal_itstring nullable

how another niche reuses the move

audiencestring nullable

the viewer it is made for

title_devicestring nullable

packaging: the title's device, one of curiosity_gap, contrarian_claim, specific_number, how_to, listicle, challenge, story, question, warning, comparison, authority, timeliness, identity_callout, other

title_templatestring nullable

packaging: the title as a fill-in structure with {placeholders}

thumbnail_textstring nullable

packaging: the words printed on the thumbnail, as a vision model read them; null when none

thumbnail_subjectstring nullable

packaging: what the picture shows

thumbnail_emotionstring nullable

packaging: the feeling it signals

thumbnail_compositionstring nullable

packaging: how the frame is built

thumbnail_devicesstring[]

packaging: up to four of face_closeup, big_text, arrow_or_circle, before_after, number, contrast_color, object_hero, screenshot, split_screen, action_shot, collage, minimal, other

gapstring nullable

packaging: what the thumbnail shows that the title does not say, and the question that leaves

Example response

{
  "about_subject": "yes",
  "age_days": 584,
  "analysed": true,
  "audience": "people curious about cold plunges",
  "auto_captions": false,
  "baseline_videos": 28,
  "beats": [
    {
      "beat": "hook",
      "does": "admits he nearly quit",
      "from": 1,
      "to": 1
    },
    {
      "beat": "promise",
      "does": "holds back the result",
      "from": 2,
      "to": 2
    }
  ],
  "channel": "Someone",
  "channel_handle": "someone",
  "channel_id": "UC0000000000000000000001",
  "channel_median_views": 85000,
  "duration_s": 1104,
  "find_id": "7c8d9e0f-1a2b-4c3d-8e4f-5a6b7c8d9e0f",
  "hook": "I got into freezing water every single morning for a month, and by day nine I wanted to quit.",
  "hook_end_s": 7.4,
  "hook_lines": 1,
  "hook_seconds": 7.4,
  "hook_start_s": 0.2,
  "hook_type": "story_open",
  "hook_words": 18,
  "intro": [
    {
      "n": 1,
      "t": 0.2,
      "text": "I got into freezing water every single morning for a month, and by day nine I wanted to quit."
    },
    {
      "n": 2,
      "t": 7.4,
      "text": "But what happened to my sleep by the end is the reason I am still doing it."
    }
  ],
  "intro_seconds": 60,
  "intro_text": "I got into freezing water every single morning for a month, and by day nine I wanted to quit. But what happened to my sleep by the end is the reason I am still doing it.",
  "kind": "long",
  "language": "English",
  "mechanism": "\"By day nine I wanted to quit\" admits the cost before any benefit, so the viewer trusts what follows and waits to hear why he stayed.",
  "open_loop": "What happened to his sleep?",
  "outlier": 28.2,
  "platform": "youtube",
  "player_url": "https://www.youtube.com/embed/dQw4w9WgXcQ",
  "posted_at": "2025-03-02T15:00:00Z",
  "posted_exact": false,
  "promise": "You will see what a month of cold plunges really changes.",
  "rank": 1,
  "run_id": "8f1c2d3e-4b5a-4c6d-8e7f-9a0b1c2d3e4f",
  "score": 2.4,
  "steal_it": "Open on the moment you nearly gave up, then hold the result back.",
  "template": "I did {hard thing} every day for {time}, and by {early point} I wanted to quit.",
  "thumbnail_url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hq720.jpg",
  "title": "I Cold Plunged Every Day For 30 Days",
  "title_link": "The first line repeats the title's thirty days and adds the low point.",
  "video_id": "dQw4w9WgXcQ",
  "views": 2400000,
  "views_per_day": 4109.6,
  "watch_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
  "why": "28x this channel's usual 85K views"
}

Changes

No recorded changes to this operation across all 1 revision of this API.