{
  "openapi": "3.0.1",
  "info": {
    "title": "Facebook Ad Library Winning Ads Finder: AI creative breakdown",
    "description": "First 25 ads free. Facebook Ad Library winning ads: collapses variants, drops dead, political and seen ads, scores each Facebook and Instagram creative by days running, adds an AI hook, angle and offer. Pay per qualified ad. Free demo on any plan; live search runs on your own Apify account.",
    "version": "0.3",
    "x-build-id": "GzGsGOpHuRhjEZgs0"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/rich_minds~fb-ad-library-winning-ads/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-rich_minds-fb-ad-library-winning-ads",
        "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/rich_minds~fb-ad-library-winning-ads/runs": {
      "post": {
        "operationId": "runs-sync-rich_minds-fb-ad-library-winning-ads",
        "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/rich_minds~fb-ad-library-winning-ads/run-sync": {
      "post": {
        "operationId": "run-sync-rich_minds-fb-ad-library-winning-ads",
        "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": {
          "searchTerms": {
            "title": "Search terms (what your competitors sell)",
            "type": "array",
            "description": "Keywords searched in the Meta Ad Library, one search per term — a product (<i>posture corrector</i>), a niche (<i>dog harness</i>) or a claim (<i>vitamin c serum</i>). Each term runs as an Ad Library keyword search in your <b>country</b>. The prefilled terms are the demo's: type your own and press Start — that starts the live search on your Apify plan (it runs a Store Actor; capped by <b>Max source spend</b>) instead of the free sample. If your plan cannot run Store Actors, paste records you already have into <b>Ad Library records to process</b> (list mode, any plan).",
            "items": {
              "type": "string"
            }
          },
          "productBrief": {
            "title": "Your product / offer (for the AI)",
            "type": "string",
            "description": "Describe what <b>you</b> sell in one or two sentences. The AI scores how well each competitor ad's angle would transfer to your product (fit score) and rewrites its angle for your product — never copying their brand, claims or prices. Leave empty for the creative breakdown only."
          },
          "preset": {
            "title": "Start from a ready niche search (one click)",
            "enum": [
              "custom",
              "dtc-shopify",
              "dropshipping-products"
            ],
            "type": "string",
            "description": "Pick a niche and press Start: it fills the search fields you left empty and runs the live Ad Library search (spend-capped by <code>maxDiscoveryChargeUsd</code>). Your own values always win. <b>Custom</b> = fill the fields yourself.",
            "default": "custom"
          },
          "minScore": {
            "title": "Minimum final score (0–100)",
            "minimum": 0,
            "maximum": 100,
            "type": "integer",
            "description": "The field that decides what you pay: ads whose final score (winner score, blended 60/40 with the AI fit score when you gave a product brief) is below this are discarded and <b>not charged</b>. 70+ = winners only.",
            "default": 40
          },
          "maxDiscoveryChargeUsd": {
            "title": "Max source spend (USD)",
            "minimum": 0.01,
            "maximum": 1000,
            "type": "number",
            "description": "Hard cap on what the source Actor run may charge your account in <b>actor</b> mode — $0.50 in the form and for an API or agent call that leaves it out, so a first real search can never cost more. Raise it for bigger searches.",
            "default": 0.5
          },
          "maxQualified": {
            "title": "Max qualified ads to output",
            "minimum": 1,
            "maximum": 10000,
            "type": "integer",
            "description": "The cap on what <b>this Actor</b> charges per run: at most this many qualified ads are delivered and billed, best first — the worst case is 100 × $0.012 = <b>$1.20</b> with AI on ($0.30 with AI off), plus the source's own cap above (Max source spend). Your first 25 ads are free.",
            "default": 100
          },
          "enableAi": {
            "title": "AI creative breakdown",
            "type": "boolean",
            "description": "The AI writes the hook, angle, offer, CTA, audience and emotional trigger with verbatim evidence quotes, a fit score against your product brief and a rewrite of the angle for your product. <b>On = $0.012 per qualified ad + AI tokens; off = $0.003</b> (rule-based winner score, offer and hook only).",
            "default": true
          },
          "notifyEmail": {
            "title": "E-mail me the new ads (optional)",
            "type": "string",
            "description": "After every run with at least one new ad, the run's digest (how many are new, the top 10 with links and hooks) is e-mailed here through Apify's send-mail Actor. Schedule the run weekly and the new winning ads come to your inbox — no Slack or Zapier needed. Never sent for the free demo."
          },
          "maxAdsToScan": {
            "title": "Max ads to scan (source)",
            "minimum": 1,
            "maximum": 10000,
            "type": "integer",
            "description": "Total ads the source scrapes across all searches — what it bills on your account (≈ $0.00075 each, so 150 ≈ $0.11). Variants, dead and filtered ads among them are never charged here.",
            "default": 150
          },
          "competitorPages": {
            "title": "Competitor Facebook pages",
            "type": "array",
            "description": "Facebook page URLs (or page names) of the competitors to watch — every ad they run is scanned, sorted by impressions. Use it for weekly competitor monitoring next to, or instead of, search terms.",
            "items": {
              "type": "string"
            }
          },
          "country": {
            "title": "Country",
            "enum": [
              "ALL",
              "US",
              "GB",
              "CA",
              "AU",
              "DE",
              "FR",
              "ES",
              "IT",
              "NL",
              "BR",
              "MX",
              "IN",
              "IE",
              "NZ",
              "AF",
              "AL",
              "DZ",
              "AD",
              "AO",
              "AG",
              "AR",
              "AM",
              "AT",
              "AZ",
              "BS",
              "BH",
              "BD",
              "BB",
              "BY",
              "BE",
              "BZ",
              "BJ",
              "BT",
              "BO",
              "BA",
              "BW",
              "BN",
              "BG",
              "BF",
              "BI",
              "KH",
              "CM",
              "CV",
              "CF",
              "TD",
              "CL",
              "CN",
              "CO",
              "KM",
              "CG",
              "CD",
              "CR",
              "CI",
              "HR",
              "CY",
              "CZ",
              "DK",
              "DJ",
              "DM",
              "DO",
              "EC",
              "EG",
              "SV",
              "GQ",
              "ER",
              "EE",
              "SZ",
              "ET",
              "FJ",
              "FI",
              "GA",
              "GM",
              "GE",
              "GH",
              "GR",
              "GD",
              "GT",
              "GN",
              "GW",
              "GY",
              "HT",
              "HN",
              "HK",
              "HU",
              "IS",
              "ID",
              "IQ",
              "IL",
              "JM",
              "JP",
              "JO",
              "KZ",
              "KE",
              "KI",
              "XK",
              "KW",
              "KG",
              "LA",
              "LV",
              "LB",
              "LS",
              "LR",
              "LY",
              "LI",
              "LT",
              "LU",
              "MO",
              "MG",
              "MW",
              "MY",
              "MV",
              "ML",
              "MT",
              "MH",
              "MR",
              "MU",
              "FM",
              "MD",
              "MC",
              "MN",
              "ME",
              "MA",
              "MZ",
              "MM",
              "NA",
              "NR",
              "NP",
              "NI",
              "NE",
              "NG",
              "MK",
              "NO",
              "OM",
              "PK",
              "PW",
              "PS",
              "PA",
              "PG",
              "PY",
              "PE",
              "PH",
              "PL",
              "PT",
              "PR",
              "QA",
              "RO",
              "RU",
              "RW",
              "KN",
              "LC",
              "VC",
              "WS",
              "SM",
              "ST",
              "SA",
              "SN",
              "RS",
              "SC",
              "SL",
              "SG",
              "SK",
              "SI",
              "SB",
              "SO",
              "ZA",
              "KR",
              "SS",
              "LK",
              "SR",
              "SE",
              "CH",
              "TW",
              "TJ",
              "TZ",
              "TH",
              "TL",
              "TG",
              "TO",
              "TT",
              "TN",
              "TR",
              "TM",
              "TV",
              "UG",
              "UA",
              "AE",
              "UY",
              "UZ",
              "VU",
              "VE",
              "VN",
              "YE",
              "ZM",
              "ZW"
            ],
            "type": "string",
            "description": "The Ad Library country searched — pick from the list (<b>All countries</b> searches every country). Over the API send the two-letter code (<code>US</code>, <code>GB</code>, <code>DE</code> …) or <code>ALL</code>; <code>UK</code>, <code>USA</code> and country names are mapped for you, anything else stops the run at once with the valid codes.",
            "default": "US"
          },
          "activeStatus": {
            "title": "Ad status",
            "enum": [
              "active",
              "all",
              "inactive"
            ],
            "type": "string",
            "description": "<b>Active</b> = ads still running today (the winners); <b>All</b> also includes ads that stopped; <b>Inactive</b> = only stopped ads. Used in the search and as a free filter.",
            "default": "active"
          },
          "mediaType": {
            "title": "Media type",
            "enum": [
              "all",
              "image",
              "video"
            ],
            "type": "string",
            "description": "Only image or only video creatives — in the search and as a free filter.",
            "default": "all"
          },
          "period": {
            "title": "Page ads from the last …",
            "enum": [
              "all",
              "last24h",
              "last7d",
              "last14d",
              "last30d"
            ],
            "type": "string",
            "description": "For <b>competitor pages</b>: only ads seen in this window.",
            "default": "all"
          },
          "maxAdsPerSearch": {
            "title": "Max ads per search / page",
            "minimum": 1,
            "maximum": 5000,
            "type": "integer",
            "description": "The most ads the source takes from one search term or page, so one broad term cannot use the whole scan budget.",
            "default": 50
          },
          "minWinnerScore": {
            "title": "Minimum winner score (0–100)",
            "minimum": 0,
            "maximum": 100,
            "type": "integer",
            "description": "The free rule bar applied before any AI token is spent: days running (up to 40 points), still active (15), variants (20), 2+ placements (10), impressions when Meta publishes them (15). 70+ = winner, 40–69 = promising.",
            "default": 40
          },
          "minDaysRunning": {
            "title": "Minimum days running",
            "minimum": 0,
            "maximum": 3650,
            "type": "integer",
            "description": "Drop ads younger than this — an ad that has run for weeks is the only public sign that it pays for itself.",
            "default": 7
          },
          "minVariants": {
            "title": "Minimum variants",
            "minimum": 1,
            "maximum": 10000,
            "type": "integer",
            "description": "API only — hidden on the form. Only creatives the advertiser runs in at least this many variants (Meta's collation count — a scaled creative has many).",
            "default": 1
          },
          "platforms": {
            "title": "Placements (Facebook, Instagram …)",
            "type": "array",
            "description": "Keep ads shown on at least one of these placements. Empty = any.",
            "items": {
              "type": "string",
              "enum": [
                "facebook",
                "instagram",
                "messenger",
                "audience_network",
                "threads"
              ],
              "enumTitles": [
                "Facebook",
                "Instagram",
                "Messenger",
                "Audience Network",
                "Threads"
              ]
            }
          },
          "excludeAdvertisers": {
            "title": "Advertisers to skip",
            "type": "array",
            "description": "Your own brand, your clients or anyone you do not want in the list — a page name (part of it), page id or landing domain.",
            "items": {
              "type": "string"
            }
          },
          "includePoliticalAds": {
            "title": "Include political / issue ads",
            "type": "boolean",
            "description": "API only — hidden on the form. Off by default: political and social-issue ads are dropped before any charge.",
            "default": false
          },
          "adLanguage": {
            "title": "Ad text language",
            "enum": [
              "any",
              "en",
              "de",
              "fr",
              "es",
              "it",
              "pt",
              "nl"
            ],
            "type": "string",
            "description": "Keep only ads whose copy is in this language (a stop-word guess; ads it cannot tell are kept).",
            "default": "any"
          },
          "targetFlags": {
            "title": "Target flags (any of)",
            "type": "array",
            "description": "Only deliver ads that have at least one of these flags (pick from the list), e.g. free shipping, a discount, 30+ days running, a video creative. Leave empty to keep everything. Over the API send the flag names from the README's flag table, e.g. <code>free_shipping</code> (<code>freeShipping</code> works too); an unknown name stops the run at once with the list of valid ones.",
            "items": {
              "type": "string",
              "enum": [
                "long_running",
                "active_now",
                "many_variants",
                "multi_platform",
                "has_discount",
                "free_shipping",
                "has_price",
                "bundle_offer",
                "free_trial",
                "urgency",
                "video_creative",
                "carousel_creative",
                "ai_generated_media",
                "no_landing_page"
              ],
              "enumTitles": [
                "Running for 30 days or more — the public sign of a profitable ad",
                "Still running today",
                "5 or more variants of the same creative (the advertiser is scaling it)",
                "Shown on 2 or more placements (Facebook, Instagram, Messenger, Audience Network)",
                "A percentage discount in the copy",
                "Free shipping or delivery in the copy",
                "A price with currency in the copy",
                "A buy-X-get-Y / bundle offer",
                "A free trial or risk-free guarantee",
                "Urgency or scarcity wording (limited time, ends tonight …)",
                "The creative is a video",
                "The creative is a carousel",
                "Meta labels the media as digitally created or altered",
                "No landing URL on the ad"
              ]
            }
          },
          "llmProvider": {
            "title": "AI model access",
            "enum": [
              "apify",
              "byok"
            ],
            "type": "string",
            "description": "<b>Apify (no keys)</b> — the AI runs through Apify's built-in OpenRouter proxy; tokens are billed to your Apify account at OpenRouter's rates. <b>My own key</b> — your Gemini / Groq / OpenAI / Anthropic key instead; a free-tier key assesses only a few ads per run — expect 1–3 AI checks (2 calls at a time, one after a rate limit, then the 3 borderline ads retried one by one) — and the rest keep their rule score; a paid Gemini / Groq key (billing on) assesses every ad. A slow own key measured up to 27 s per ad, so the worst case per 100 qualified ads is ≈ 25 min (2 calls at a time; rate-limit waits stop after 60 s per run). The AI stops before the run's timeout and the rest keep their rule score.",
            "default": "apify"
          },
          "llmModel": {
            "title": "AI model",
            "type": "string",
            "description": "Leave empty for the default (<code>anthropic/claude-haiku-4.5</code> through Apify; <code>google:gemini-3.5-flash-lite</code> with your own key — a free Gemini key works). Apify mode takes an OpenRouter slug such as <code>openai/gpt-4.1-mini</code>; own-key mode takes <code>provider:model</code>, e.g. <code>anthropic:claude-haiku-4-5-20251001</code> for an Anthropic key."
          },
          "llmApiKey": {
            "title": "Your API key (own-key mode only)",
            "type": "string",
            "description": "Required when <b>AI model access</b> is <i>My own API key</i>. Stored encrypted by Apify, never logged."
          },
          "outputLanguage": {
            "title": "AI output language",
            "type": "string",
            "description": "API only — hidden on the form. Language of the creative breakdown and of the rewrite for your product (quotes stay in the ad's language).",
            "default": "English"
          },
          "aiCandidateMultiplier": {
            "title": "AI candidate pool (× max qualified)",
            "minimum": 1,
            "maximum": 5,
            "type": "integer",
            "description": "API only — hidden on the form. How many of the best rule-scored ads get the AI pass, as a multiple of <b>Max qualified</b>. Higher = more thorough, slower, more tokens.",
            "default": 2
          },
          "sendAlertsTo": {
            "title": "Send alerts to (Slack, Discord, Teams, Google Chat, Telegram or webhook)",
            "type": "string",
            "description": "Paste one or more URLs, one per line — the service is detected from the address: a Slack or Discord channel webhook, a Teams Workflows or Google Chat space webhook, your Telegram bot's send link (<code>https://api.telegram.org/bot&lt;token&gt;/sendMessage?chat_id=@yourchannel</code>) or any other https URL (Zapier, Make, n8n, your CRM), which gets the ads as JSON. After every run with at least one new ad, the digest (how many are new, the top 10 with hook and days running, change alerts, competitors to watch and the report link) is posted there. Never sent for the free demo. Headers, batching and signing: <i>Delivery details (advanced)</i>."
          },
          "changeAlerts": {
            "title": "Change alerts on ads you already have",
            "type": "boolean",
            "description": "For a scheduled monitor: every run also re-checks the ads you received before and adds one <code>rowType: alert</code> row when a competitor <b>stopped</b> an ad (a loser killed) or an ad passed <b>30 / 60 / 90 days</b> (a winner confirmed) — in the dataset, the e-mail digest and the webhook. <b>$0.003 per alert</b> (<code>ad-alert</code>), never on the free demo. To see an ad stop, the search also fetches stopped ads (inside <b>Max ads to scan</b>); new rows stay active-only.",
            "default": false
          },
          "advertiserReports": {
            "title": "Competitor report rows",
            "type": "boolean",
            "description": "Adds one <code>rowType: advertiser</code> row per top advertiser of the run (up to 10): active ads, new this run, stopped, ads running 30+ days, average days running, share of voice, top angles and offers, best ad — the per-competitor summary an agency forwards. <b>$0.02 per advertiser row</b> (<code>advertiser-report</code>), never on the free demo (which shows one sample row). A weekly monitor with nothing new still gets its reports.",
            "default": false
          },
          "enrichLandingPages": {
            "title": "Read each ad's landing page",
            "type": "boolean",
            "description": "Opens the landing page of every qualified ad and adds <code>landingPage</code>: store platform (Shopify, WooCommerce …), product title, price, rating and reviews count — what the page states itself, nothing guessed. <b>$0.004 per page that yields a store or a product</b> (<code>landing-enriched</code>); unreachable pages and your free ads cost nothing. Adds a few seconds per 5 pages; stops before the run's timeout.",
            "default": false
          },
          "onlyNewAds": {
            "title": "Only ads new since the last run",
            "type": "boolean",
            "description": "Remembers every ad (and each of its variants) you received, in a named key-value store on your account, and skips it in later runs — a weekly schedule delivers and charges only new ads. Off: earlier ads come again, marked <code>isNewSinceLastRun: false</code>.",
            "default": true
          },
          "dedupeTtlDays": {
            "title": "Deliver an ad again after (days)",
            "minimum": 0,
            "maximum": 3650,
            "type": "integer",
            "description": "How long a delivered ad stays remembered. 0 = never deliver or charge it again (the default — an ad keeps its archive id). A number of days lets an ad you already had reach you again after that many days — charged again as a new ad.",
            "default": 0
          },
          "historyDatasetName": {
            "title": "Keep a running log (dataset name)",
            "type": "string",
            "description": "API only — hidden on the form. Optional. Type a name (e.g. <code>fb-ad-library-winning-ads-seen-log</code>) and every run appends its new ads with the date to that named dataset on your account — one list across months to connect to Google Sheets or your BI tool once. Empty = off. Costs nothing extra.",
            "default": ""
          },
          "sourceMode": {
            "title": "Where do the ads come from?",
            "enum": [
              "actor",
              "dataset",
              "list"
            ],
            "type": "string",
            "description": "<b>actor</b> — search the Meta Ad Library live with <code>curious_coder/facebook-ads-library-scraper</code> on your account (≈ $0.00075 per ad scanned, billed by that Actor; needs an Apify plan that can run Store Actors — if yours cannot, the run stops at once and nothing is charged). <b>dataset</b> — qualify an existing dataset from that scraper or from <code>apify/facebook-ads-scraper</code>. <b>list</b> — Ad Library records you paste in. <b>Bring your own data:</b> rows or a dataset ID, and you pay only for the analysis — the source Actor is never run. The mode you choose always runs as chosen; only the untouched sample records next to search terms you typed switch to the live search (spend-capped). <code>{}</code> over the API runs the free demo (8 sample ads) — nothing charged.",
            "default": "actor"
          },
          "autoSwitchToLive": {
            "title": "Typed search next to the sample starts the live search",
            "type": "boolean",
            "description": "API only — hidden on the form. On (default): search terms typed next to the untouched sample records start the live search (spend-capped; <code>OUTPUT.switchedToLive</code> names them). Off: the mode you send is the mode that runs — the sample stays the free demo and the status names the terms it did not search. API pipelines that must never start a paid read on their own: send <code>false</code>.",
            "default": true
          },
          "datasetId": {
            "title": "Dataset",
            "type": "string",
            "description": "Only for <b>dataset</b> mode: a dataset of <code>curious_coder/facebook-ads-library-scraper</code> or <code>apify/facebook-ads-scraper</code>. Pick it so the Actor is granted read access to it."
          },
          "itemsList": {
            "title": "Ad Library records to process",
            "type": "array",
            "description": "Only for <b>list</b> mode. JSON array of Meta Ad Library records in either scraper's shape (<code>ad_archive_id</code> + <code>snapshot</code>, or <code>adArchiveID</code> + <code>snapshot</code>). Records without an archive id are skipped and never charged."
          },
          "discoveryActorId": {
            "title": "Source Actor (advanced)",
            "type": "string",
            "description": "Actor used in <b>actor</b> mode. Any Actor whose output has the Meta Ad Library fields listed in the README works.",
            "default": "curious_coder/facebook-ads-library-scraper"
          },
          "discoveryInput": {
            "title": "Source Actor input overrides",
            "type": "object",
            "description": "API only — hidden on the form. Only for <b>actor</b> mode. Keys merged over the input this Actor builds for the source (e.g. <code>{\"scrapeAdDetails\": true}</code>). See the source Actor's input schema."
          },
          "maxToProcess": {
            "title": "Max candidates to process",
            "minimum": 1,
            "maximum": 20000,
            "type": "integer",
            "description": "API only — hidden on the form. Upper bound on how many ads are scored in one run (controls run time). Default = 3 × max qualified."
          },
          "proxyConfiguration": {
            "title": "Proxy",
            "type": "object",
            "description": "API only — hidden on the form. Not used by this Actor itself (the source Actor brings its own proxy); kept for compatibility."
          },
          "webhookUrl": {
            "title": "Webhook URL (optional)",
            "type": "string",
            "description": "API only — hidden on the form. Qualified ads are POSTed here as JSON (Zapier, Make, n8n, your CRM). For a chat channel use <b>Send alerts to</b> above — a Slack webhook here would receive raw JSON. Stored encrypted — Zapier / Make hook URLs carry their secret in the path."
          },
          "webhookHeaders": {
            "title": "Webhook headers (optional)",
            "type": "object",
            "description": "API only — hidden on the form. Extra HTTP headers for the webhook, e.g. <code>{\"Authorization\": \"Bearer …\"}</code>. Stored encrypted by Apify, never logged."
          },
          "webhookBatchSize": {
            "title": "Webhook batch size",
            "minimum": 1,
            "maximum": 500,
            "type": "integer",
            "description": "API only — hidden on the form. 1 = one POST per ad the moment it is ready. Higher = one POST per N ads.",
            "default": 1
          },
          "webhookSecret": {
            "title": "Webhook signing secret (optional)",
            "type": "string",
            "description": "API only — hidden on the form. Any random string. Every webhook POST then carries <code>X-Signature: sha256=&lt;HMAC-SHA256 of the raw body with this secret&gt;</code>, so your endpoint can verify it came from this Actor. Stored encrypted by Apify, never logged."
          },
          "dedupeStoreName": {
            "title": "Dedupe store name",
            "type": "string",
            "description": "Key-value store used for the cross-run memory. Left at the default, the memory is kept per search (source, country, dataset and your filter set — adding a search term or a page keeps it, rewording the product brief keeps it): a scheduled run never re-delivers what you already have. Running it for several clients on one account, type one name per client.",
            "default": "fb-ad-library-winning-ads-seen"
          },
          "discoveryTimeoutSecs": {
            "title": "Source run timeout, seconds (API only)",
            "minimum": 60,
            "maximum": 86400,
            "type": "integer",
            "description": "API only — hidden on the form. How long the source Store Actor may run before its partial results are used. Raise it when the status says the source stopped early.",
            "default": 3600
          },
          "slackWebhookUrl": {
            "title": "Slack webhook URL (API only)",
            "type": "string",
            "description": "API only — hidden on the form, where <code>sendAlertsTo</code> takes it. Slack incoming-webhook URL for the digest."
          },
          "discordWebhookUrl": {
            "title": "Discord webhook URL (API only)",
            "type": "string",
            "description": "API only — hidden on the form, where <code>sendAlertsTo</code> takes it. Discord channel webhook URL for the digest."
          },
          "teamsWebhookUrl": {
            "title": "Microsoft Teams webhook URL (API only)",
            "type": "string",
            "description": "API only — hidden on the form, where <code>sendAlertsTo</code> takes it. Teams Workflows webhook URL for the digest."
          },
          "googleChatWebhookUrl": {
            "title": "Google Chat webhook URL (API only)",
            "type": "string",
            "description": "API only — hidden on the form, where <code>sendAlertsTo</code> takes it. Google Chat space webhook URL for the digest."
          },
          "telegramUrl": {
            "title": "Telegram sendMessage link (API only)",
            "type": "string",
            "description": "API only — hidden on the form, where <code>sendAlertsTo</code> takes it. The bot's sendMessage link with its chat_id."
          }
        }
      },
      "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}