{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/hookdetector-com/json-schema/hookdetector-com-packaging-in-schema.json",
  "title": "PackagingIn",
  "x-generated": "2026-11-11",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/hookdetector-com-openapi.json#/components/schemas/PackagingIn",
  "properties": {
    "topic": {
      "type": "string",
      "maxLength": 500,
      "minLength": 3,
      "title": "Topic",
      "description": "the subject to research, 3 to 500 characters, in any language. Or a YouTube address instead of a subject: a channel's (https://www.youtube.com/@name, or just @name) returns that channel's own outliers, its recent long-form uploads that beat its usual; a long-form video's (https://www.youtube.com/watch?v=...) returns that one video, whatever its multiple. A Short's address is refused (422)"
    },
    "count": {
      "type": "integer",
      "maximum": 30.0,
      "minimum": 1.0,
      "title": "Count",
      "description": "how many packages to deliver, 1 to 30",
      "default": 12
    },
    "language": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "maxLength": 60,
      "title": "Language",
      "description": "optional, up to 60 characters: the language the videos should be spoken in, in words or as a tag (\"Spanish\", \"pt-BR\"). Left out, it is read from the topic's own language"
    },
    "country": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "pattern": "^[A-Za-z]{2}$",
      "title": "Country",
      "description": "optional, an assigned ISO 3166-1 alpha-2 code (US, GB, MA): searches YouTube as seen from this country. It steers the search; it does not filter the channels"
    },
    "min_outlier": {
      "type": [
        "number",
        "null"
      ],
      "maximum": 100.0,
      "minimum": 1.5,
      "title": "Min Outlier",
      "description": "optional, 1.5 to 100 (default 2): how many times its own channel's usual views a video must have to count as an outlier. Only outliers are ever delivered"
    },
    "posted_within_days": {
      "type": [
        "integer",
        "null"
      ],
      "enum": [
        30,
        90,
        365,
        730,
        null
      ],
      "title": "Posted Within Days",
      "description": "optional, how recent the videos must be, as days: 30, 90, 365, 730. Null or left out means everything since 2023-01-01; nothing older is ever delivered"
    },
    "channel_size": {
      "type": [
        "string",
        "null"
      ],
      "enum": [
        "small",
        "medium",
        "large",
        null
      ],
      "title": "Channel Size",
      "description": "optional: only videos from channels of this size, by what the channel's uploads usually get (its median views, the figure the outlier is measured against): small (under 20,000), medium (up to 200,000) or large. Null or left out: any size"
    },
    "ideas": {
      "type": [
        "integer",
        "null"
      ],
      "maximum": 10.0,
      "minimum": 0.0,
      "title": "Ideas",
      "description": "optional, 0 to 10 (default 6): how many written packages (a title and a thumbnail concept) to add for the subject; 0 for none"
    },
    "reuse": {
      "type": "boolean",
      "title": "Reuse",
      "description": "start from the videos your last long or packaging run on this topic already bought (within a week), so the second tab on a topic costs little",
      "default": true
    },
    "content_type": {
      "type": [
        "string",
        "null"
      ],
      "enum": [
        "long",
        "short",
        null
      ],
      "title": "Content Type",
      "description": "optional: \"long\" (long-form videos, the default) or \"short\" (YouTube Shorts): the kind of video whose packages to find. A Short is measured against its own channel's Shorts"
    },
    "filters": {
      "type": [
        "object",
        "null"
      ],
      "title": "Filters",
      "description": "optional bounds, every one optional: min_multiple and max_multiple (views over the channel's median, 1 to 1000), min_views, max_views, min_channel_median, max_channel_median, min_duration_s, max_duration_s; on the Library (and a library preset) also min_comments, max_comments, posted_within_days (7, 30, 90, 365, 730) and language. No delivered find falls outside one; a min_multiple above the bar raises it"
    },
    "preset_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Preset Id",
      "description": "optional: start from a saved preset of this tab (save_preset); filters sent with it win over the preset's"
    }
  },
  "type": "object",
  "required": [
    "topic"
  ]
}