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.
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 |
JSON Schema
{
"$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.
Call it yourself
curl for this page
curl "https://apis.io/api/v1/json-schemas/hookdetector-com-find-out"
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.