{
  "openapi": "3.0.1",
  "info": {
    "title": "YouTube Scraper $2/1K — Videos, Channels, Comments, Transcripts",
    "description": "Scrape YouTube videos, channels, comments, and transcripts in one tool — by keyword or by video, channel, and playlist URL. Get rich per-video metadata, comments with replies, and translated transcripts. Incremental mode and RAG-ready output included.",
    "version": "0.1",
    "x-build-id": "VkgMNWpBfKTSmc3EH"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/blackfalcondata~youtube-data-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-blackfalcondata-youtube-data-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/blackfalcondata~youtube-data-scraper/runs": {
      "post": {
        "operationId": "runs-sync-blackfalcondata-youtube-data-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/blackfalcondata~youtube-data-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-blackfalcondata-youtube-data-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "startUrls": {
            "title": "🔗 Start URLs",
            "type": "array",
            "description": "YouTube video, channel, or playlist URLs to scrape directly (one per line). Each entry is routed automatically by type and processed as its own task. You can also paste a bare 11-character video ID (e.g. \"dQw4w9WgXcQ\") or a bare @handle (e.g. \"@MrBeast\"). Merged with Video / Channel / Playlist URLs below. Used by all modes. Default: empty. Also accepts the aliases `url`, `urls`, and `startURLs` (and the typed lists `videoUrls` / `channelUrls` / `playlistUrls` below all merge in here).",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "videoUrls": {
            "title": "Video URLs",
            "type": "array",
            "description": "Video URLs or bare 11-character video IDs (one per line), e.g. \"https://www.youtube.com/watch?v=dQw4w9WgXcQ\" or \"dQw4w9WgXcQ\". Use this to paste a list of videos separately from channels and playlists. Merged with Start URLs. Feeds Video, Comments, and Transcripts modes. Default: empty. Also accepts the aliases `videoUrl`, `url`, and `urls`.",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "channelUrls": {
            "title": "Channel URLs",
            "type": "array",
            "description": "Channel URLs or bare @handles (one per line), e.g. \"https://www.youtube.com/@MrBeast\" or \"@veritasium\". Use this to paste a list of channels separately from videos and playlists. Merged with Start URLs. Feeds Video mode (channel uploads) and Channel mode (channel profiles). Default: empty. Also accepts the alias `channelUrl`.",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "playlistUrls": {
            "title": "Playlist URLs",
            "type": "array",
            "description": "Playlist URLs or bare playlist IDs (one per line), e.g. \"https://www.youtube.com/playlist?list=PLxxxx\" or \"PLxxxx\". Each playlist's videos are collected and tagged with their source `playlistId`. Merged with Start URLs. Feeds Video mode. Default: empty. Also accepts the alias `playlistUrl`.",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "searchQueries": {
            "title": "Search Queries",
            "type": "array",
            "description": "Keywords to search on YouTube (one per line), e.g. \"nodejs tutorial\". Each query runs as a separate search task and respects the Search Filters below. You can also paste several queries separated by commas. Required for the Trending mode (to define the topic to rank). Default: empty. Also accepts the aliases `query`, `q`, `keyword`, `keywords`, `searchQuery`, and `search`.",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "scrapeVideos": {
            "title": "Scrape Videos",
            "type": "boolean",
            "description": "Collect video items (metadata, stats, descriptions) from search results, channel pages, playlists, and pasted video URLs. This is the default mode. Default: true.",
            "default": true
          },
          "scrapeChannels": {
            "title": "Scrape Channels",
            "type": "boolean",
            "description": "Collect channel items (name, subscriber count, video count, country, links) from channel URLs/@handles or channel results in a search. Combine with Channel URLs or a search using Result Type = Channels only. Default: false.",
            "default": false
          },
          "scrapeComments": {
            "title": "Scrape Comments",
            "type": "boolean",
            "description": "Fetch comments for each scraped video. Requires a video target (search, channel, playlist, or pasted Video URL). Comments automatically use US residential IPs when needed (residential access required on your account). Tune volume/order in the Comments settings below. Default: false.",
            "default": false
          },
          "scrapeTranscripts": {
            "title": "Scrape Transcripts",
            "type": "boolean",
            "description": "Download full transcripts (captions) for each scraped video. Requires a video target. ⚠️ Needs US residential IPs (RESIDENTIAL group, country US) or transcripts come back empty; also runs slower (a browser step). Configure format, language, and translation in the Transcripts settings below. Default: false.",
            "default": false
          },
          "scrapeTrending": {
            "title": "Scrape Trending",
            "type": "boolean",
            "description": "Collect the most-viewed recent videos for your topic, ranked by view count over a recent upload window. Requires at least one Search Query, or a Trending Topic, to define what to rank. Default: false.",
            "default": false
          },
          "trendingCategory": {
            "title": "Trending Topic",
            "type": "string",
            "description": "Optional extra topic to rank when Scrape Trending is on, e.g. \"music\", \"gaming\", or \"movies\". Added alongside your search queries as a topic to find the most-viewed recent videos for. Applies to Trending mode. Default: blank (rank only your search queries)."
          },
          "sortBy": {
            "title": "🔀 Sort By",
            "enum": [
              "relevance",
              "date",
              "viewCount",
              "rating"
            ],
            "type": "string",
            "description": "Order of search results. Applies to Search mode. Options: Relevance (YouTube's default ranking); Upload date (newest first); View count (most-viewed first); Rating (highest-rated first). Default: \"relevance\".",
            "default": "relevance"
          },
          "uploadDate": {
            "title": "Upload Date Filter",
            "enum": [
              "hour",
              "today",
              "week",
              "month",
              "year"
            ],
            "type": "string",
            "description": "Restrict search results to videos uploaded within this window. Applies to Search mode. Options: Last hour; Today (last 24 hours); This week (last 7 days); This month (last 30 days); This year (last 365 days). Default: no restriction (any date)."
          },
          "videoDuration": {
            "title": "Video Duration",
            "enum": [
              "short",
              "medium",
              "long"
            ],
            "type": "string",
            "description": "Filter search results by video length. Applies to Search mode. Options: Short (under 4 minutes); Medium (4–20 minutes); Long (over 20 minutes). Default: no restriction (any length)."
          },
          "resultType": {
            "title": "Result Type",
            "enum": [
              "video",
              "channel",
              "any"
            ],
            "type": "string",
            "description": "Which kind of YouTube results a search should return. Applies to Search mode. Options: Videos only; Channels only (use together with Scrape Channels to find channels by keyword); Any (mixed results). To scrape a playlist, paste its playlist URL into Start URLs instead. Default: \"video\".",
            "default": "video"
          },
          "filterHd": {
            "title": "HD Only",
            "type": "boolean",
            "description": "Only return videos available in high definition. Applies to Search mode. Default: false.",
            "default": false
          },
          "filterSubtitles": {
            "title": "Has Subtitles/CC",
            "type": "boolean",
            "description": "Only return videos that have subtitles or closed captions. Useful as a pre-filter before transcript scraping. Applies to Search mode. Default: false.",
            "default": false
          },
          "filterCreativeCommons": {
            "title": "Creative Commons",
            "type": "boolean",
            "description": "Only return videos published under a Creative Commons license. Applies to Search mode. Default: false.",
            "default": false
          },
          "filterLive": {
            "title": "Live Only",
            "type": "boolean",
            "description": "Only return videos that are currently live. Applies to Search mode. Default: false.",
            "default": false
          },
          "filter4k": {
            "title": "4K Only",
            "type": "boolean",
            "description": "Only return videos available in 4K resolution. Applies to Search mode. Default: false.",
            "default": false
          },
          "filter360": {
            "title": "360° Only",
            "type": "boolean",
            "description": "Only return 360-degree videos. Applies to Search mode. Default: false.",
            "default": false
          },
          "filterHdr": {
            "title": "HDR Only",
            "type": "boolean",
            "description": "Only return videos available in HDR. Applies to Search mode. Default: false.",
            "default": false
          },
          "includeKeywords": {
            "title": "Include Keywords",
            "type": "array",
            "description": "Post-fetch filter: keep only results whose title or description contains at least one of these keywords (case-insensitive), e.g. [\"react\", \"vue\"]. Applies to all modes. Default: empty (no filtering).",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "excludeKeywords": {
            "title": "Exclude Keywords",
            "type": "array",
            "description": "Post-fetch filter: drop results whose title or description contains any of these keywords (case-insensitive), e.g. [\"shorts\", \"reaction\"]. Applies to all modes. Default: empty (no filtering).",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "fromDate": {
            "title": "From Date",
            "type": "string",
            "description": "Post-fetch filter: only include videos published on or after this date. Accepts an absolute ISO 8601 date (e.g. \"2024-01-01\") or a relative offset into the past (e.g. \"7d\", \"2 weeks\", \"3 months\", \"1 year\"). Applies to all modes. Default: no lower bound."
          },
          "toDate": {
            "title": "To Date",
            "type": "string",
            "description": "Post-fetch filter: only include videos published on or before this date. Accepts an absolute ISO 8601 date (e.g. \"2024-12-31\") or a relative offset into the past (e.g. \"1d\"). Applies to all modes. Default: no upper bound."
          },
          "maxAgeDays": {
            "title": "Max age (days)",
            "minimum": 0,
            "type": "integer",
            "description": "Post-fetch filter: only include videos published within the last N days (e.g. 30). When combined with From Date, the more restrictive cutoff wins. Applies to all modes. Default: blank (no age limit)."
          },
          "customFilters": {
            "title": "Custom Filters",
            "type": "string",
            "description": "Advanced post-fetch filter expression (DSL) evaluated against each output item, e.g. \"viewCount > 100000 AND durationSec < 600\". For power users; leave blank for no custom filtering. Applies to all modes. Note: enrichment-derived fields (category, keywords, hashtags, description) are only populated at detailLevel \"standard\" and above — filtering on one of these at detailLevel \"basic\" leaves it null and excludes every record. Default: blank."
          },
          "channelVideoType": {
            "title": "Channel Video Type",
            "enum": [
              "videos",
              "shorts",
              "live"
            ],
            "type": "string",
            "description": "Which tab to scrape when visiting a channel. Applies to Channel URLs in Video mode. Options: Regular videos (the Videos tab, long-form uploads); Shorts (the Shorts tab); Live streams (past and upcoming live broadcasts). Default: \"videos\".",
            "default": "videos"
          },
          "channelSortOrder": {
            "title": "Channel Sort Order",
            "enum": [
              "newest",
              "oldest",
              "popular"
            ],
            "type": "string",
            "description": "Order of videos listed on a channel page. Applies to the Videos tab of Channel URLs in Video mode (sort is not available on the Shorts or Live tabs and is ignored there). Options: Newest first; Oldest first; Most popular (by view count). Default: \"newest\".",
            "default": "newest"
          },
          "fetchAbout": {
            "title": "Fetch Channel About Info",
            "type": "boolean",
            "description": "Fetch the channel About panel to fill in join date, country, total view count, and external links on channel items. Disable to skip the extra request for faster channel runs. Applies to Channel mode. Default: true.",
            "default": true
          },
          "transcriptFormat": {
            "title": "Transcript Format",
            "enum": [
              "segments",
              "plaintext",
              "srt",
              "vtt",
              "xml"
            ],
            "type": "string",
            "description": "Output format for transcript data. Applies to Transcripts mode. Options: Timed segments (JSON array of { text, startMs, durationMs }); Plain text (one continuous string in `fullText`); SRT subtitles (numbered, timestamped subtitle blocks); WebVTT subtitles (web-standard caption format); Raw XML (the unprocessed caption document). All variants also include the plain `fullText`. Default: \"segments\".",
            "default": "segments"
          },
          "transcriptLanguage": {
            "title": "Transcript Language",
            "type": "string",
            "description": "BCP-47 language code for the desired transcript track, e.g. \"en\" or \"de\". Applies to Transcripts mode. Default: blank (use the video's default caption language)."
          },
          "translateTo": {
            "title": "Translate Transcript To",
            "type": "string",
            "description": "BCP-47 language code to auto-translate the transcript into, e.g. \"en\" or \"es\". Applies to Transcripts mode. Default: blank (no translation)."
          },
          "preferAutoGenerated": {
            "title": "Prefer Auto-Generated Transcripts",
            "type": "boolean",
            "description": "When both a manual and an auto-generated transcript exist for a video, prefer the auto-generated one. Applies to Transcripts mode. Default: false (prefer the manual transcript).",
            "default": false
          },
          "transcriptFields": {
            "title": "Transcript Fields to Include",
            "type": "array",
            "description": "Emit only this subset of transcript output fields, e.g. [\"fullText\", \"srt\"]. Applies to Transcripts mode. Default: empty (include all transcript fields).",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "commentsPerVideo": {
            "title": "Comments (per video)",
            "minimum": 0,
            "type": "integer",
            "description": "Maximum number of comments to fetch per video. Set 0 for unlimited. Applies to Comments mode. Default: 100.",
            "default": 100
          },
          "commentsSort": {
            "title": "Comments Sort Order",
            "enum": [
              "top",
              "new"
            ],
            "type": "string",
            "description": "Comment retrieval order. Applies to Comments mode. Options: Top comments (YouTube's most-relevant ranking, usually most-liked first); Newest first (most recently posted). Default: \"top\".",
            "default": "top"
          },
          "includeReplies": {
            "title": "Include Replies",
            "type": "boolean",
            "description": "Also fetch replies to each top-level comment (nested under the comment's `replies` field). Increases run time and result volume. Applies to Comments mode. Default: false.",
            "default": false
          },
          "maxResults": {
            "title": "Max results (per run)",
            "minimum": 0,
            "type": "integer",
            "description": "Maximum number of videos and channels to collect across all tasks. Comments and transcripts are extra per-video records, not counted against this limit (set their volume with Comments per video / Scrape transcripts). Set 0 for unlimited. Default: 50. Aliases: `limit`, `max`, `maxItems`, `maxVideos`.",
            "default": 50
          },
          "maxResultsPerQuery": {
            "title": "💯 Max results (per query)",
            "minimum": 0,
            "type": "integer",
            "description": "Cap on the number of videos and channels each individual search query or target (channel / playlist) may contribute, applied independently of Max Results (per run). Like Max Results, this caps videos and channels only — comments and transcripts are additional per-video records (controlled by Comments per video and Scrape transcripts) and are not counted against it. Useful for spreading a budget evenly across several queries. Default: blank (no per-query cap)."
          },
          "maxShorts": {
            "title": "Max Shorts",
            "minimum": 0,
            "type": "integer",
            "description": "Maximum number of Shorts (vertical, short-form clips) to include, applied independently of Max Results. Extra Shorts are dropped while regular videos are kept. Set 0 to exclude Shorts entirely. Applies to Video and Trending modes. Default: blank (no separate Shorts cap)."
          },
          "maxRunSeconds": {
            "title": "Max run time (seconds)",
            "minimum": 0,
            "type": "integer",
            "description": "Optional soft cap on how long the run may spend fetching, e.g. 300 for five minutes. When the run nears this limit it stops collecting new items and saves whatever it has gathered so far. Applies to all modes. Default: blank (no soft cap)."
          },
          "includeShorts": {
            "title": "Include Shorts",
            "type": "boolean",
            "description": "Include YouTube Shorts (vertical, short-form clips) in video results. Turn off to keep only regular long-form videos. Applies to Video and Trending modes. Default: true.",
            "default": true
          },
          "shortsOnly": {
            "title": "Shorts Only",
            "type": "boolean",
            "description": "Return only YouTube Shorts and drop regular videos. Takes precedence over Include Shorts. Applies to Video and Trending modes. Default: false.",
            "default": false
          },
          "detailLevel": {
            "title": "Detail Level",
            "enum": [
              "basic",
              "standard",
              "detailed",
              "complete"
            ],
            "type": "string",
            "description": "How much metadata to fetch per video. Higher levels return more fields but may require an extra request per item (slower, higher cost). Applies to Video and Trending modes. Options: Basic (only the fields available from the listing — title, channel, view count, duration; no per-video request); Standard (adds video-page fields such as likes, full description, category, keywords); Detailed (adds extra metadata such as chapters, available captions, hashtags); Complete (every field the actor can extract). Default: \"standard\".",
            "default": "standard"
          },
          "descriptionFormat": {
            "title": "Description Format",
            "enum": [
              "text",
              "html",
              "markdown",
              "all"
            ],
            "type": "string",
            "description": "Output format for video and channel description text. Applies to Video and Channel modes. Options: Plain text (raw text in `descriptionText`); HTML (escaped, with <br> for newlines and <a> for links, in `descriptionHtml`); Markdown (line breaks preserved, URLs linkified, in `descriptionMarkdown`); All formats (every variant alongside the plain text). Default: \"text\".",
            "default": "text"
          },
          "excludeEmptyFields": {
            "title": "Exclude Empty Fields",
            "type": "boolean",
            "description": "Strip null and empty fields from output items to reduce dataset size and make records easier to read. Applies to all modes. Default: false.",
            "default": false
          },
          "includeRunMetadata": {
            "title": "📣 Include Run Metadata",
            "type": "boolean",
            "description": "Append a `_meta` block (run id, actor id, start/finish time, a non-sensitive input summary, and per-mode counts) to every output item, useful for auditing which run produced a record. Applies to all modes. Default: false.",
            "default": false
          },
          "ragOutput": {
            "title": "RAG Output (embedding-ready)",
            "type": "boolean",
            "description": "Output embedding-ready documents ({id, text, metadata}) instead of raw records — ready for RAG pipelines and vector databases. Applies to all modes. Default: false.",
            "default": false
          },
          "ragChunkSize": {
            "title": "RAG Chunk Size (characters)",
            "minimum": 0,
            "maximum": 10000,
            "type": "integer",
            "description": "Split long text into chunks of about this many characters (0 = one document per item). Useful for embedding long transcripts. Applies when RAG Output is on. Default: 0 (no chunking).",
            "default": 0
          },
          "ragChunkOverlap": {
            "title": "RAG Chunk Overlap (characters)",
            "minimum": 0,
            "maximum": 2000,
            "type": "integer",
            "description": "Character overlap between consecutive chunks. Applies when RAG Output is on and a chunk size is set. Default: 0.",
            "default": 0
          },
          "country": {
            "title": "🌍 Country (2-letter code)",
            "type": "string",
            "description": "Two-letter ISO country code used to localize YouTube results, e.g. \"US\", \"DE\", or \"GB\". Affects which results and trending content are returned. Applies to all modes. Default: \"US\". Also accepts the aliases `gl`, `geo`, and `region`.",
            "default": "US"
          },
          "hl": {
            "title": "UI Language",
            "type": "string",
            "description": "BCP-47 language code for the YouTube interface language, e.g. \"en\" or \"de\". Affects the label text in responses (such as category names). Applies to all modes. Default: \"en\". Also accepts the aliases `lang` and `language`.",
            "default": "en"
          },
          "translateMetadataTo": {
            "title": "Translate Title/Description To",
            "type": "string",
            "description": "Language code (e.g. \"es\" or \"ja\") to also fetch each video's title and description in. Uses YouTube's own localization (creator-supplied or auto-translated; coverage varies per video and language) and adds `translatedTitle` / `translatedDescription` alongside the originals. Adds an extra request per video. Applies to Video mode. Default: blank (no translation)."
          },
          "proxyConfiguration": {
            "title": "Proxy Configuration",
            "type": "object",
            "description": "Route requests through a proxy or your own proxy URLs. ⚠️ Transcripts, direct video-URL detail, and engagement counts (likes/comments/subscribers) need US residential IPs — choose the RESIDENTIAL group with country US here, or supply your own US residential-IP proxy URLs. Comments automatically use US residential IPs when needed (requires residential access on your Apify account; billed as platform usage). Search, Channel, and Trending modes work on the default proxy. Recommended for larger runs to spread requests across IP addresses. Applies to all modes. Default: proxy enabled. Also accepts the alias `proxy`.",
            "default": {
              "useApifyProxy": true
            }
          },
          "incrementalMode": {
            "title": "Incremental Mode",
            "type": "boolean",
            "description": "Track which items have been seen before. On subsequent runs with the same inputs, output only new and changed items (the rest are skipped). Applies to all modes. Default: false.",
            "default": false
          },
          "stateKey": {
            "title": "State Key",
            "type": "string",
            "description": "Optional stable key identifying the incremental state to load and update, e.g. \"my-tech-feed\". Use the same key across runs to continue the same incremental feed. Applies when Incremental Mode is on. Default: blank (a key derived from the search inputs is used)."
          },
          "emitUnchanged": {
            "title": "Emit Unchanged Items",
            "type": "boolean",
            "description": "When Incremental Mode is on, also output records whose tracked content has not changed since the last run (marked `changeType: \"UNCHANGED\"`). By default unchanged items are skipped so each run returns only new and changed items. Tracked content is title, description, channel, category, and the Short flag for videos (counts such as views/likes do not count as a change). Default: false.",
            "default": false
          },
          "emitExpired": {
            "title": "Emit Expired Items",
            "type": "boolean",
            "description": "When Incremental Mode is on, output a small stub record (id plus `changeType: \"EXPIRED\"`) for items that have disappeared since the last run. Only applies to fully-covered single-channel or single-playlist scrapes, where a missing item is a reliable signal it was removed; broad searches and capped runs never emit EXPIRED. Expired stubs carry no scraped fields and are not billed as results. Default: false.",
            "default": false
          },
          "telegramToken": {
            "title": "Telegram Bot Token",
            "type": "string",
            "description": "Telegram bot token from @BotFather. Required to send Telegram notifications when a run finishes. Default: blank (Telegram notifications off)."
          },
          "telegramChatId": {
            "title": "💬 Telegram Chat ID",
            "type": "string",
            "description": "Telegram chat or channel ID to send notifications to, e.g. \"-100123456789\". Required when Telegram Bot Token is set. Default: blank."
          },
          "discordWebhookUrl": {
            "title": "Discord Webhook URL",
            "type": "string",
            "description": "Discord incoming webhook URL to post a run-summary message to. Default: blank (Discord notifications off)."
          },
          "slackWebhookUrl": {
            "title": "Slack Webhook URL",
            "type": "string",
            "description": "Slack incoming webhook URL to post a run-summary message to. Default: blank (Slack notifications off)."
          },
          "whatsappAccessToken": {
            "title": "WhatsApp Access Token",
            "type": "string",
            "description": "WhatsApp Cloud API permanent access token (a System User token from Meta Business). Required to send WhatsApp notifications. Default: blank (WhatsApp notifications off)."
          },
          "whatsappPhoneNumberId": {
            "title": "WhatsApp Phone Number ID",
            "type": "string",
            "description": "Your WhatsApp Business phone-number ID (numeric, from the Meta dashboard). Required when WhatsApp Access Token is set. Default: blank."
          },
          "whatsappTo": {
            "title": "WhatsApp Recipient",
            "type": "string",
            "description": "Recipient phone number in E.164 format without the leading +, e.g. \"14155552671\". Required when WhatsApp Access Token is set. Default: blank."
          },
          "webhookUrl": {
            "title": "Webhook URL",
            "type": "string",
            "description": "URL that receives a JSON POST with { metadata, items } after each run. Works with n8n, Make, Zapier, or any custom backend. Default: blank (no webhook)."
          },
          "webhookHeaders": {
            "title": "Webhook Headers",
            "type": "object",
            "description": "Optional JSON object of custom HTTP headers sent with the webhook, e.g. {\"Authorization\": \"Bearer token\"}. Applies when Webhook URL is set. Default: none."
          },
          "notificationLimit": {
            "title": "Max Items Per Notification",
            "minimum": 1,
            "maximum": 20,
            "type": "integer",
            "description": "Maximum number of items included in each notification message. Range 1–20. Applies when any notification channel is configured. Default: 5.",
            "default": 5
          },
          "notifyOnlyChanges": {
            "title": "Notify Only New/Updated",
            "type": "boolean",
            "description": "When Incremental Mode is on, only send notifications for NEW and UPDATED items (skip unchanged ones). Applies when a notification channel is configured. Default: false.",
            "default": false
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}