Awzor Media LLC · Schema

FindOut

One result of a long or packaging run. Sent back exactly as stored: a long find has the opening fields, a packaging find the title and thumbnail fields, and a field one kind does not have is absent, never null.

Hook DetectionTikTokInstagramYouTubeContent CreationVideo Analytics

Properties

Name Type Description
find_id string the id to keep, reject or read it by; absent on an item of `progress.items`
run_id string the run that found it
kind string long or packaging
rank integer its place in the run, from 1: the strongest outlier first
verdict stringnull keep, reject or null
video_id string the YouTube video id
platform string always "youtube"
title string the video's title as YouTube shows it, word for word (runs of spaces read as one)
channel stringnull the channel's name
channel_handle stringnull the channel's @handle, without the @
watch_url string where to watch it
player_url string an iframe src that plays it (16:9)
thumbnail_url string the video's thumbnail on YouTube's image host; `thumbnail_urls` lists every size, best first, and a size a video lacks answers 404
views integer views when the run read it
likes integernull likes, when YouTube gave them
comments integernull comments, when YouTube gave them
age_days numbernull days since it was posted, when the run read it
views_per_day numbernull views divided by age_days
baseline_videos integernull how many recent uploads the channel's usual was measured on
found_by stringnull the search that surfaced it
duration_s integernull length in seconds; always over 180
posted_at stringnull 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_exact boolean whether posted_at is the real timestamp
channel_median_views integernull the channel's usual: the median views of its recent long-form uploads
outlier numbernull views divided by channel_median_views: 28.2 means 28 times what this channel normally gets
outlier_score integer 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 dif
channel_size stringnull the channel by what its uploads usually get (channel_median_views): small, medium or large
seen_before boolean 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_read boolean 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_id stringnull the channel's YouTube id (UC...)
thumbnail_urls array every thumbnail size, best first; a size a video lacks answers 404
score numbernull the ranking score outlier_score is scaled from
hook_lines integer 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_s number 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_s number long: the second the hook starts: 0 or close to it, later when a sponsor read or a greeting came first
hook_words integer long: the hook's length in words
auto_captions boolean long: true when the opening carries almost no punctuation (auto captions): its sentences are not marked and names may be misheard
about_subject stringnull 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). N
hook_type_other stringnull long: the device in words when hook_type is "other"
title_device_other stringnull packaging: the device in words when title_device is "other"
multiple numbernull views over channel_median_views, one decimal: 12.4 means 12.4 times what this channel normally gets (the number 1of10 and vidIQ show). Null when the channel was not measured
multiple_band stringnull the multiple's band: 10x (10 or more), 5x (5 to under 10), 2x (2 to under 5), under 2x (a video asked for by its address, or a bar set under 2); null with no multiple
content_type stringnull the kind of video: long (long-form) or short (a YouTube Short)
outlier_tier stringnull outlier (under 5 times the channel's usual), strong (5 to 10) or breakout (10 or more)
likes_per_1k numbernull likes for every 1,000 views
comments_per_1k numbernull comments for every 1,000 views
style_match booleannull when the request asked for a kind of opening or title: whether this one is that kind. Null when it asked for none
angle stringnull the specific angle the video takes on the subject
format stringnull long: the kind of video, one of talking_head, voiceover, vlog, tutorial, interview, documentary, challenge, review, story, other
opens_with stringnull long: how the first seconds begin, one of cold_open, greeting, teaser, question, sponsor, other
thumbnail_checked boolean packaging: true when thumbnail_url is the size YouTube really served and the analysis looked at
thumbnail_sha256 string packaging: a digest of the picture the analysis looked at; a later run reuses the analysis only while YouTube serves the same picture
analysed_at string packaging: when the thumbnail was looked at (ISO 8601); a reused analysis keeps its own date
title_chars integer packaging: the title's length in characters
cut_on_phone boolean 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 (a
thumbnail_text_role stringnull 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.
title_overlap numbernull 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 stringnull 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.
thumbnail_faces integernull packaging: how many faces the thumbnail shows
thumbnail_colors stringnull packaging: the colours that carry the frame
why stringnull one line naming the outlier in words
language stringnull the language spoken, as YouTube names the caption track
analysed boolean false when the model could not analyse it: the find is still real, its analysis fields are null
hook string 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. T
hook_seconds numbernull long: the second the hook ends; the same number as `hook_end_s`, kept for older readers
intro array 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_text string long: the same words as one string
intro_seconds integer long: how much of the opening was read
hook_type stringnull 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,
mechanism stringnull long: why the opening holds a viewer, quoting it word for word
promise stringnull what the viewer is told they will get
open_loop stringnull long: the question the opening leaves unanswered
title_link stringnull long: how the first lines pay off the title
beats array 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
template stringnull long: the hook as a fill-in structure with {placeholders}
steal_it stringnull how another niche reuses the move
audience stringnull the viewer it is made for
title_device stringnull 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, othe
title_template stringnull packaging: the title as a fill-in structure with {placeholders}
thumbnail_text stringnull packaging: the words printed on the thumbnail, as a vision model read them; null when none
thumbnail_subject stringnull packaging: what the picture shows
thumbnail_emotion stringnull packaging: the feeling it signals
thumbnail_composition stringnull packaging: how the frame is built
thumbnail_devices array 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
gap stringnull packaging: what the thumbnail shows that the title does not say, and the question that leaves
visible_action stringnull packaging: the single thing happening in the picture, one sentence with a verb (a model's reading)
title_carries stringnull packaging: what only the title tells the viewer
picture_adds stringnull packaging: what only the picture adds that the title does not say
text_box arraynull packaging: the box around the biggest line of printed words, [left, top, right, bottom] in thousandths of the width and height; null with no words
thumb_metrics objectnull packaging: the thumbnail measured in code from its pixels: palette (three colours with their share %), brightness, contrast, saturation and busyness (0 to 100), text_px_210 (the biggest words' height
View JSON Schema on GitHub

JSON Schema

hookdetector-com-find-out-schema.json Raw ↑
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/hookdetector-com/json-schema/hookdetector-com-find-out-schema.json",
  "title": "FindOut",
  "description": "One result of a long or packaging run. Sent back exactly as stored: a long find has\nthe opening fields, a packaging find the title and thumbnail fields, and a field one\nkind does not have is absent, never null.",
  "x-generated": "2026-11-11",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/hookdetector-com-openapi.json#/components/schemas/FindOut",
  "properties": {
    "find_id": {
      "type": "string",
      "format": "uuid",
      "title": "Find Id",
      "description": "the id to keep, reject or read it by; absent on an item of `progress.items`"
    },
    "run_id": {
      "type": "string",
      "format": "uuid",
      "title": "Run Id",
      "description": "the run that found it"
    },
    "kind": {
      "type": "string",
      "enum": [
        "long",
        "packaging"
      ],
      "title": "Kind",
      "description": "long or packaging"
    },
    "rank": {
      "type": "integer",
      "title": "Rank",
      "description": "its place in the run, from 1: the strongest outlier first"
    },
    "verdict": {
      "type": [
        "string",
        "null"
      ],
      "enum": [
        "keep",
        "reject",
        null
      ],
      "title": "Verdict",
      "description": "keep, reject or null"
    },
    "video_id": {
      "type": "string",
      "title": "Video Id",
      "description": "the YouTube video id"
    },
    "platform": {
      "type": "string",
      "title": "Platform",
      "description": "always \"youtube\""
    },
    "title": {
      "type": "string",
      "title": "Title",
      "description": "the video's title as YouTube shows it, word for word (runs of spaces read as one)"
    },
    "channel": {
      "type": [
        "string",
        "null"
      ],
      "title": "Channel",
      "description": "the channel's name"
    },
    "channel_handle": {
      "type": [
        "string",
        "null"
      ],
      "title": "Channel Handle",
      "description": "the channel's @handle, without the @"
    },
    "watch_url": {
      "type": "string",
      "title": "Watch Url",
      "description": "where to watch it"
    },
    "player_url": {
      "type": "string",
      "title": "Player Url",
      "description": "an iframe src that plays it (16:9)"
    },
    "thumbnail_url": {
      "type": "string",
      "title": "Thumbnail Url",
      "description": "the video's thumbnail on YouTube's image host; `thumbnail_urls` lists every size, best first, and a size a video lacks answers 404"
    },
    "views": {
      "type": "integer",
      "title": "Views",
      "description": "views when the run read it"
    },
    "likes": {
      "type": [
        "integer",
        "null"
      ],
      "title": "Likes",
      "description": "likes, when YouTube gave them"
    },
    "comments": {
      "type": [
        "integer",
        "null"
      ],
      "title": "Comments",
      "description": "comments, when YouTube gave them"
    },
    "age_days": {
      "type": [
        "number",
        "null"
      ],
      "title": "Age Days",
      "description": "days since it was posted, when the run read it"
    },
    "views_per_day": {
      "type": [
        "number",
        "null"
      ],
      "title": "Views Per Day",
      "description": "views divided by age_days"
    },
    "baseline_videos": {
      "type": [
        "integer",
        "null"
      ],
      "title": "Baseline Videos",
      "description": "how many recent uploads the channel's usual was measured on"
    },
    "found_by": {
      "type": [
        "string",
        "null"
      ],
      "title": "Found By",
      "description": "the search that surfaced it"
    },
    "duration_s": {
      "type": [
        "integer",
        "null"
      ],
      "title": "Duration S",
      "description": "length in seconds; always over 180"
    },
    "posted_at": {
      "type": [
        "string",
        "null"
      ],
      "title": "Posted At",
      "description": "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_exact": {
      "type": "boolean",
      "title": "Posted Exact",
      "description": "whether posted_at is the real timestamp"
    },
    "channel_median_views": {
      "type": [
        "integer",
        "null"
      ],
      "title": "Channel Median Views",
      "description": "the channel's usual: the median views of its recent long-form uploads"
    },
    "outlier": {
      "type": [
        "number",
        "null"
      ],
      "title": "Outlier",
      "description": "views divided by channel_median_views: 28.2 means 28 times what this channel normally gets"
    },
    "outlier_score": {
      "type": "integer",
      "title": "Outlier Score",
      "description": "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": {
      "type": [
        "string",
        "null"
      ],
      "enum": [
        "small",
        "medium",
        "large",
        null
      ],
      "title": "Channel Size",
      "description": "the channel by what its uploads usually get (channel_median_views): small, medium or large"
    },
    "seen_before": {
      "type": "boolean",
      "title": "Seen Before",
      "description": "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_read": {
      "type": "boolean",
      "title": "Analysis From Earlier Read",
      "description": "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_id": {
      "type": [
        "string",
        "null"
      ],
      "title": "Channel Id",
      "description": "the channel's YouTube id (UC...)"
    },
    "thumbnail_urls": {
      "items": {
        "type": "string"
      },
      "type": "array",
      "title": "Thumbnail Urls",
      "description": "every thumbnail size, best first; a size a video lacks answers 404"
    },
    "score": {
      "type": [
        "number",
        "null"
      ],
      "title": "Score",
      "description": "the ranking score outlier_score is scaled from"
    },
    "hook_lines": {
      "type": "integer",
      "title": "Hook Lines",
      "description": "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_s": {
      "type": "number",
      "title": "Hook End S",
      "description": "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_s": {
      "type": "number",
      "title": "Hook Start S",
      "description": "long: the second the hook starts: 0 or close to it, later when a sponsor read or a greeting came first"
    },
    "hook_words": {
      "type": "integer",
      "title": "Hook Words",
      "description": "long: the hook's length in words"
    },
    "auto_captions": {
      "type": "boolean",
      "title": "Auto Captions",
      "description": "long: true when the opening carries almost no punctuation (auto captions): its sentences are not marked and names may be misheard"
    },
    "about_subject": {
      "type": [
        "string",
        "null"
      ],
      "enum": [
        "yes",
        "partly",
        null
      ],
      "title": "About Subject",
      "description": "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_other": {
      "type": [
        "string",
        "null"
      ],
      "title": "Hook Type Other",
      "description": "long: the device in words when hook_type is \"other\""
    },
    "title_device_other": {
      "type": [
        "string",
        "null"
      ],
      "title": "Title Device Other",
      "description": "packaging: the device in words when title_device is \"other\""
    },
    "multiple": {
      "type": [
        "number",
        "null"
      ],
      "title": "Multiple",
      "description": "views over channel_median_views, one decimal: 12.4 means 12.4 times what this channel normally gets (the number 1of10 and vidIQ show). Null when the channel was not measured"
    },
    "multiple_band": {
      "type": [
        "string",
        "null"
      ],
      "enum": [
        "10x",
        "5x",
        "2x",
        "under 2x",
        null
      ],
      "title": "Multiple Band",
      "description": "the multiple's band: 10x (10 or more), 5x (5 to under 10), 2x (2 to under 5), under 2x (a video asked for by its address, or a bar set under 2); null with no multiple"
    },
    "content_type": {
      "type": [
        "string",
        "null"
      ],
      "enum": [
        "long",
        "short",
        null
      ],
      "title": "Content Type",
      "description": "the kind of video: long (long-form) or short (a YouTube Short)"
    },
    "outlier_tier": {
      "type": [
        "string",
        "null"
      ],
      "enum": [
        "outlier",
        "strong",
        "breakout",
        null
      ],
      "title": "Outlier Tier",
      "description": "outlier (under 5 times the channel's usual), strong (5 to 10) or breakout (10 or more)"
    },
    "likes_per_1k": {
      "type": [
        "number",
        "null"
      ],
      "title": "Likes Per 1K",
      "description": "likes for every 1,000 views"
    },
    "comments_per_1k": {
      "type": [
        "number",
        "null"
      ],
      "title": "Comments Per 1K",
      "description": "comments for every 1,000 views"
    },
    "style_match": {
      "type": [
        "boolean",
        "null"
      ],
      "title": "Style Match",
      "description": "when the request asked for a kind of opening or title: whether this one is that kind. Null when it asked for none"
    },
    "angle": {
      "type": [
        "string",
        "null"
      ],
      "title": "Angle",
      "description": "the specific angle the video takes on the subject"
    },
    "format": {
      "type": [
        "string",
        "null"
      ],
      "title": "Format",
      "description": "long: the kind of video, one of talking_head, voiceover, vlog, tutorial, interview, documentary, challenge, review, story, other"
    },
    "opens_with": {
      "type": [
        "string",
        "null"
      ],
      "title": "Opens With",
      "description": "long: how the first seconds begin, one of cold_open, greeting, teaser, question, sponsor, other"
    },
    "thumbnail_checked": {
      "type": "boolean",
      "title": "Thumbnail Checked",
      "description": "packaging: true when thumbnail_url is the size YouTube really served and the analysis looked at"
    },
    "thumbnail_sha256": {
      "type": "string",
      "title": "Thumbnail Sha256",
      "description": "packaging: a digest of the picture the analysis looked at; a later run reuses the analysis only while YouTube serves the same picture"
    },
    "analysed_at": {
      "type": "string",
      "title": "Analysed At",
      "description": "packaging: when the thumbnail was looked at (ISO 8601); a reused analysis keeps its own date"
    },
    "title_chars": {
      "type": "integer",
      "title": "Title Chars",
      "description": "packaging: the title's length in characters"
    },
    "cut_on_phone": {
      "type": "boolean",
      "title": "Cut On Phone",
      "description": "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_role": {
      "type": [
        "string",
        "null"
      ],
      "title": "Thumbnail Text Role",
      "description": "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_overlap": {
      "type": [
        "number",
        "null"
      ],
      "title": "Title Overlap",
      "description": "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": {
      "type": [
        "string",
        "null"
      ],
      "enum": [
        "yes",
        "partly",
        "no",
        null
      ],
      "title": "On Subject",
      "description": "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_faces": {
      "type": [
        "integer",
        "null"
      ],
      "title": "Thumbnail Faces",
      "description": "packaging: how many faces the thumbnail shows"
    },
    "thumbnail_colors": {
      "type": [
        "string",
        "null"
      ],
      "title": "Thumbnail Colors",
      "description": "packaging: the colours that carry the frame"
    },
    "why": {
      "type": [
        "string",
        "null"
      ],
      "title": "Why",
      "description": "one line naming the outlier in words"
    },
    "language": {
      "type": [
        "string",
        "null"
      ],
      "title": "Language",
      "description": "the language spoken, as YouTube names the caption track"
    },
    "analysed": {
      "type": "boolean",
      "title": "Analysed",
      "description": "false when the model could not analyse it: the find is still real, its analysis fields are null"
    },
    "hook": {
      "type": "string",
      "title": "Hook",
      "description": "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_seconds": {
      "type": [
        "number",
        "null"
      ],
      "title": "Hook Seconds",
      "description": "long: the second the hook ends; the same number as `hook_end_s`, kept for older readers"
    },
    "intro": {
      "items": {
        "type": "object"
      },
      "type": "array",
      "title": "Intro",
      "description": "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_text": {
      "type": "string",
      "title": "Intro Text",
      "description": "long: the same words as one string"
    },
    "intro_seconds": {
      "type": "integer",
      "title": "Intro Seconds",
      "description": "long: how much of the opening was read"
    },
    "hook_type": {
      "type": [
        "string",
        "null"
      ],
      "title": "Hook Type",
      "description": "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."
    },
    "mechanism": {
      "type": [
        "string",
        "null"
      ],
      "title": "Mechanism",
      "description": "long: why the opening holds a viewer, quoting it word for word"
    },
    "promise": {
      "type": [
        "string",
        "null"
      ],
      "title": "Promise",
      "description": "what the viewer is told they will get"
    },
    "open_loop": {
      "type": [
        "string",
        "null"
      ],
      "title": "Open Loop",
      "description": "long: the question the opening leaves unanswered"
    },
    "title_link": {
      "type": [
        "string",
        "null"
      ],
      "title": "Title Link",
      "description": "long: how the first lines pay off the title"
    },
    "beats": {
      "items": {
        "type": "object"
      },
      "type": "array",
      "title": "Beats",
      "description": "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"
    },
    "template": {
      "type": [
        "string",
        "null"
      ],
      "title": "Template",
      "description": "long: the hook as a fill-in structure with {placeholders}"
    },
    "steal_it": {
      "type": [
        "string",
        "null"
      ],
      "title": "Steal It",
      "description": "how another niche reuses the move"
    },
    "audience": {
      "type": [
        "string",
        "null"
      ],
      "title": "Audience",
      "description": "the viewer it is made for"
    },
    "title_device": {
      "type": [
        "string",
        "null"
      ],
      "title": "Title Device",
      "description": "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_template": {
      "type": [
        "string",
        "null"
      ],
      "title": "Title Template",
      "description": "packaging: the title as a fill-in structure with {placeholders}"
    },
    "thumbnail_text": {
      "type": [
        "string",
        "null"
      ],
      "title": "Thumbnail Text",
      "description": "packaging: the words printed on the thumbnail, as a vision model read them; null when none"
    },
    "thumbnail_subject": {
      "type": [
        "string",
        "null"
      ],
      "title": "Thumbnail Subject",
      "description": "packaging: what the picture shows"
    },
    "thumbnail_emotion": {
      "type": [
        "string",
        "null"
      ],
      "title": "Thumbnail Emotion",
      "description": "packaging: the feeling it signals"
    },
    "thumbnail_composition": {
      "type": [
        "string",
        "null"
      ],
      "title": "Thumbnail Composition",
      "description": "packaging: how the frame is built"
    },
    "thumbnail_devices": {
      "items": {
        "type": "string"
      },
      "type": "array",
      "title": "Thumbnail Devices",
      "description": "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"
    },
    "gap": {
      "type": [
        "string",
        "null"
      ],
      "title": "Gap",
      "description": "packaging: what the thumbnail shows that the title does not say, and the question that leaves"
    },
    "visible_action": {
      "type": [
        "string",
        "null"
      ],
      "title": "Visible Action",
      "description": "packaging: the single thing happening in the picture, one sentence with a verb (a model's reading)"
    },
    "title_carries": {
      "type": [
        "string",
        "null"
      ],
      "title": "Title Carries",
      "description": "packaging: what only the title tells the viewer"
    },
    "picture_adds": {
      "type": [
        "string",
        "null"
      ],
      "title": "Picture Adds",
      "description": "packaging: what only the picture adds that the title does not say"
    },
    "text_box": {
      "items": {
        "type": "integer"
      },
      "type": [
        "array",
        "null"
      ],
      "title": "Text Box",
      "description": "packaging: the box around the biggest line of printed words, [left, top, right, bottom] in thousandths of the width and height; null with no words"
    },
    "thumb_metrics": {
      "type": [
        "object",
        "null"
      ],
      "title": "Thumb Metrics",
      "description": "packaging: the thumbnail measured in code from its pixels: palette (three colours with their share %), brightness, contrast, saturation and busyness (0 to 100), text_px_210 (the biggest words' height when the thumbnail is 210 px wide, from text_box), text_reads_at_210 (6.2 px or more), badge_corner_clear (no words where YouTube prints the length) and basis. Null when the picture could not be read"
    }
  },
  "additionalProperties": true,
  "type": "object"
}

Work with this as data

Every JSON Schema here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for schemas

4 MCP tools reach this
  • find_json_schemasBrowse and filter every JSON Schema in the catalog.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This JSON Schema
curl "https://apis.io/api/v1/json-schemas/hookdetector-com-find-out"
All schemas
curl "https://apis.io/api/v1/json-schemas?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.