{
  "openapi": "3.0.1",
  "info": {
    "title": "Google Maps Scraper | $1/1k Places",
    "description": "Scrape Google Maps for $1/1k places: 30+ fields, reviews, photos, hours, GPS. Enrich every result with 20+ optional add-ons: emails, phones, socials, LinkedIn, SSL, tech stack, SEO, AI contacts, jobs & icebreakers. All merged into ONE row per business. No dataset joins. MCP-ready for AI agents.",
    "version": "5.9",
    "x-build-id": "YXxutkagAwQdvFkxp"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/santamaria-automations~google-maps-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-santamaria-automations-google-maps-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/santamaria-automations~google-maps-scraper/runs": {
      "post": {
        "operationId": "runs-sync-santamaria-automations-google-maps-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/santamaria-automations~google-maps-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-santamaria-automations-google-maps-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": {
          "searchStrings": {
            "title": "Search Queries (simple)",
            "type": "array",
            "description": "Simple search strings. Each is sent directly to Google Maps. Include the location in the string for geo-targeting.",
            "items": {
              "type": "string"
            }
          },
          "queries": {
            "title": "Advanced Queries",
            "type": "array",
            "description": "Structured search queries with optional location, country code, and company ID for linking results back to your data.",
            "items": {
              "type": "object",
              "properties": {
                "query": {
                  "title": "Search Query",
                  "type": "string",
                  "description": "Search term: company name, business type, or any Google Maps search query"
                },
                "company_id": {
                  "title": "Company ID (optional)",
                  "type": "string",
                  "description": "Your internal ID, passed through to output for linking"
                },
                "location": {
                  "title": "Location",
                  "type": "string",
                  "description": "City or region for geo-targeting (e.g. 'London', 'Bavaria', 'Tokyo')"
                },
                "country": {
                  "title": "Country",
                  "type": "string",
                  "description": "ISO 3166-1 alpha-2 code (US, GB, DE, FR, JP, etc.)"
                }
              },
              "required": []
            }
          },
          "maxResultsPerQuery": {
            "title": "Max Results per Query",
            "minimum": 1,
            "maximum": 120,
            "type": "integer",
            "description": "Each query returns up to this many results. With N queries, the total you can receive is N x this value. Use 'maxTotalResults' below to cap the grand total. Google Maps returns 20 per page, max ~120 per query.",
            "default": 20
          },
          "maxTotalResults": {
            "title": "Max Total Results (optional)",
            "minimum": 1,
            "type": "integer",
            "description": "Hard cap across ALL queries combined. Leave empty for no cap. Useful for budget control when running multiple queries."
          },
          "maxResults": {
            "title": "Max Results per Query (deprecated)",
            "minimum": 1,
            "maximum": 120,
            "type": "integer",
            "description": "DEPRECATED. Use 'maxResultsPerQuery' instead. Still works (treated as per-query limit) but will be removed in a future version."
          },
          "language": {
            "title": "Language",
            "type": "string",
            "description": "Language code for the Google Maps search results themselves. Uses standard ISO 639-1 codes. Pass any ISO 639-1 language code: en, de, fr, ja, es, pt, it, ko, zh-CN, ar, nl, pl, sv, da, fi, no, cs, hu, ro, el, tr, th, vi, id, and more.",
            "default": "en"
          },
          "includeReviewCount": {
            "title": "Include exact review count (adds 2-8s per place)",
            "type": "boolean",
            "description": "Enrich each result with the exact review_count via an additional Maps Embed API request per place. The base search response already includes rating and an approximate review count — enable this only when you need the exact number (e.g. for filtering by review-count thresholds). Off by default so a first-time run stays fast.",
            "default": false
          },
          "includeReviews": {
            "title": "Include Reviews",
            "type": "boolean",
            "description": "Fetch per-place reviews (author, rating, date, text, photos, owner reply). Up to 100 reviews per place via Google's paginated BOQ endpoint. Disabled by default.",
            "default": false
          },
          "maxReviewsPerPlace": {
            "title": "Max Reviews per Place",
            "minimum": 1,
            "maximum": 200,
            "type": "integer",
            "description": "Maximum number of reviews per place. 1 to 8: single-request preview endpoint. 9 to 100: paginated via Google's internal BOQ JSON endpoint (~100 reviews max in practice). Default is 8.",
            "default": 8
          },
          "reviewsSort": {
            "title": "Reviews Sort Order",
            "enum": [
              "most_relevant",
              "newest",
              "highest_rating",
              "lowest_rating"
            ],
            "type": "string",
            "description": "Sort order for reviews. Note: when maxReviewsPerPlace is 8 or less, the preview endpoint always returns most_relevant regardless of this setting.",
            "default": "most_relevant"
          },
          "reviewsNewerThan": {
            "title": "Only Reviews Newer Than (date)",
            "type": "string",
            "description": "Filter out reviews published before this date. Format: YYYY-MM-DD (e.g. 2024-01-01). Reviews older than this date are skipped. Only applies when 'Include Reviews' is enabled."
          },
          "includePopularTimes": {
            "title": "Include Popular Times",
            "type": "boolean",
            "description": "Enrich each result with the visitor-traffic histogram (per weekday, per hour, 0-100). Adds one extra request per place (~200ms, concurrency-limited). Only places with enough foot traffic for Google to compute the histogram will have non-null data.",
            "default": false
          },
          "enableGbpCompleteness": {
            "title": "Score Google Business Profile Completeness (add-on)",
            "type": "boolean",
            "description": "For every place, score the Google Business Profile on 8 signals (website, phone, hours, description, category, photos, reviews, is_claimed). Adds `gbp_completeness` to each row with a 0-100 score, sub-scores per signal, missing fields, and a HIGH/NORMAL lead-priority flag. Zero-fetch: reads only what is already on the maps result. Runs as a separate actor: https://apify.com/santamaria-automations/gbp-completeness-audit",
            "default": false
          },
          "enableSeoAudit": {
            "title": "Extract SEO Metadata (add-on)",
            "type": "boolean",
            "description": "For every place with a website, extract SEO signals from the home page: title, meta description (with lengths), canonical URL, robots directive, HTML lang, and Open Graph title/description. Adds `seo_audit` to each row. Runs as a separate actor: https://apify.com/santamaria-automations/seo-metadata-extractor",
            "default": false
          },
          "enablePhoneValidation": {
            "title": "Validate & Enrich Phone Numbers (add-on)",
            "type": "boolean",
            "description": "For every place with a phone number, validate the number and enrich with country, line type (mobile/fixed/VoIP), carrier when known, and E.164 / international / national formatted variants. Adds `phone_validation` to each row. Skipped cleanly for places without a phone. Runs as a separate actor: https://apify.com/santamaria-automations/phone-validator",
            "default": false
          },
          "enableEmailExtraction": {
            "title": "Extract Emails, Phones & Social Links (add-on)",
            "type": "boolean",
            "description": "After scraping Maps, extract email addresses, phone numbers, and social profile URLs (LinkedIn, Facebook, Instagram, Twitter, YouTube) from each company's website. Pure regex + Cloudflare Email Protection decoder, no LLM key needed, no AI cost. Required by the Facebook Page Scraper and Email Verification add-ons since both consume its output. Runs as a separate actor: https://apify.com/santamaria-automations/website-email-scraper",
            "default": false
          },
          "enableEmailVerification": {
            "title": "Verify Extracted Emails (add-on)",
            "type": "boolean",
            "description": "After the email extractor discovers emails, run each through MX validation, disposable-domain check, role-account detection, and provider inference (Google Workspace, Microsoft 365, etc.). Auto-enables the email extractor if it isn't already on. Results land in a separate dataset in v1, join by email address downstream. Runs as a separate actor: https://apify.com/santamaria-automations/email-verifier",
            "default": false
          },
          "enableFacebookScrape": {
            "title": "Scrape Facebook Pages (add-on)",
            "type": "boolean",
            "description": "For every place whose website links to a Facebook Page, scrape the FB Page for followers, likes, category, contact info, rating, and whether the page is currently running ads (the `runs_ads` field is a strong buying-signal indicator). Adds `facebook` to each row. Higher cost per result: uses a residential proxy to avoid Facebook's login wall. Requires the Email Extractor add-on since Facebook URLs are discovered from each website by the email scraper. Runs as a separate actor: https://apify.com/santamaria-automations/facebook-pages-scraper",
            "default": false
          },
          "enableLinkedInCompanyScrape": {
            "title": "Scrape LinkedIn Company Pages (add-on)",
            "type": "boolean",
            "description": "For every place whose website links to a LinkedIn Company page, scrape the page for follower count, employee count and headcount range, industry, headquarters, founded year, company type, description, and specialties. Adds `linkedin_company` to each row. Requires the Email Extractor add-on since LinkedIn URLs are discovered from each website by the email scraper. Runs as a separate actor: https://apify.com/santamaria-automations/linkedin-company-scraper",
            "default": false
          },
          "enableTwitterScrape": {
            "title": "Scrape Twitter / X Profiles (add-on)",
            "type": "boolean",
            "description": "For every place whose website links to a Twitter / X profile, scrape the profile for follower count, following count, tweet count, media count, bio, location, verified state, and blue-verified state. Adds `twitter` to each row. Requires a residential proxy (X rate-limits datacenter IPs). Requires the Email Extractor add-on since Twitter URLs are discovered from each website by the email scraper. Runs as a separate actor: https://apify.com/santamaria-automations/twitter-x-profiles-tweets-scraper",
            "default": false
          },
          "enableInstagramScrape": {
            "title": "Scrape Instagram Profiles (add-on)",
            "type": "boolean",
            "description": "For every place whose website links to an Instagram profile, scrape the profile for followers, following, posts count, biography, external URL, verified state, business category, and business flag. Adds `instagram` to each row. Requires the Email Extractor add-on since Instagram URLs are discovered from each website by the email scraper. Runs as a separate actor: https://apify.com/santamaria-automations/instagram-scraper",
            "default": false
          },
          "enableTikTokScrape": {
            "title": "Scrape TikTok Profiles (add-on)",
            "type": "boolean",
            "description": "For every place whose website links to a TikTok profile (@handle), scrape the profile for follower count, following count, heart count, video count, signature, and verified state. Adds `tiktok` to each row. Requires the Email Extractor add-on since TikTok URLs are discovered from each website by the email scraper. Runs as a separate actor: https://apify.com/santamaria-automations/tiktok-profile-scraper",
            "default": false
          },
          "tikTokMaxVideosPerProfile": {
            "title": "TikTok — recent videos per profile",
            "minimum": 0,
            "maximum": 20,
            "type": "integer",
            "description": "How many of the most-recent videos to include for each TikTok profile (title, play count, likes, share count, comments, video URL, thumbnail, duration, is-pinned). 0 disables recent-video capture and only returns profile stats. Only applies when the TikTok add-on is enabled.",
            "default": 6
          },
          "enableYouTubeChannelScrape": {
            "title": "Scrape YouTube Channels (add-on)",
            "type": "boolean",
            "description": "For every place whose website links to a YouTube channel (@handle, /c/name, /user/name, /channel/UCxxx), scrape the channel for channel ID, handle, name, subscriber count, and up to 10 latest videos with titles, view counts, and thumbnails. Adds `youtube` to each row. Requires the Email Extractor add-on since YouTube URLs are discovered from each website by the email scraper. Runs as a separate actor: https://apify.com/santamaria-automations/youtube-channel-scraper",
            "default": false
          },
          "enableSslInspection": {
            "title": "Inspect SSL Certificate (add-on)",
            "type": "boolean",
            "description": "After scraping Maps, inspect the SSL/TLS certificate on each company's website. Returns issuer, validity dates, days-until-expiry, and a `flag` field (`ok`, `expiring_soon`, `expired`, `self_signed`, `invalid`). Great for prospecting: businesses with expired certs or self-signed setups are often behind on their tech. Runs as a separate actor: https://apify.com/santamaria-automations/ssl-certificate-inspector",
            "default": false
          },
          "enableWhoisDns": {
            "title": "Fetch WHOIS & DNS (add-on)",
            "type": "boolean",
            "description": "After scraping Maps, look up WHOIS (registrar, created date, domain age) and DNS (A / MX / TXT / NS records, has_spf, has_dmarc, has_dkim, email provider) for each company's domain. Perfect for enriching lead lists with domain-age and email-provider signals. Runs as a separate actor: https://apify.com/santamaria-automations/domain-whois-dns",
            "default": false
          },
          "enableTechStack": {
            "title": "Detect Website Tech Stack (add-on)",
            "type": "boolean",
            "description": "For every place with a website, detect the tech stack: CMS, frameworks, analytics, servers, CDN, and other technologies via a Wappalyzer-style pattern set. Adds `tech_stack` to each row with a `technologies` list and a `category_summary` grouped by CDN / analytics / web-server / etc. Runs as a separate actor: https://apify.com/santamaria-automations/website-tech-detector",
            "default": false
          },
          "enableBrokenLinkCheck": {
            "title": "Check for Broken Links (add-on)",
            "type": "boolean",
            "description": "For every place with a website, crawl the home page and one hop of internal links (up to 15 URLs, no external links) and flag any broken links (4xx / 5xx / timeouts). Adds `broken_links` to each row with `broken_count`, a `site_health_flag` (healthy / minor_issues / many_broken), and the actual broken URL list. Runs as a separate actor: https://apify.com/santamaria-automations/broken-link-checker",
            "default": false
          },
          "enablePageSpeedAudit": {
            "title": "PageSpeed + Accessibility Audit (add-on, BYO Google API key)",
            "type": "boolean",
            "description": "For every place with a website, call Google's PageSpeed Insights API v5 and return real Lighthouse Performance + Accessibility scores + Core Web Vitals (LCP, FID, CLS, FCP, TTFB, TBT, SI, TTI) + up to 20 accessibility issues per site. Adds `page_speed_audit` to each row. Requires your own Google API key (free tier: 25,000 queries/day per Google Cloud project). Get a key at https://developers.google.com/speed/docs/insights/v5/get-started. Runs as a separate actor: https://apify.com/santamaria-automations/pagespeed-accessibility-audit",
            "default": false
          },
          "enableComplianceScan": {
            "title": "Legal & Compliance Scanner (add-on)",
            "type": "boolean",
            "description": "For every place with a website, probe for Impressum / privacy policy / cookie-consent markers and return a risk flag. Detects 12 consent tools (Cookiebot, Usercentrics, OneTrust, Iubenda, TrustArc, and more) plus generic IAB TCF v2. Language-aware: missing Impressum on a German site is HIGH risk (Abmahnung-actionable); other geos MEDIUM at worst. Strong DACH lead-gen play: legal/marketing agencies filter for HIGH to build outreach lists. Adds `compliance` to each row. Runs as a separate actor: https://apify.com/santamaria-automations/compliance-scanner",
            "default": false
          },
          "enableFreshnessCheck": {
            "title": "Website Freshness Detector (add-on)",
            "type": "boolean",
            "description": "For every place with a website, probe sitemap lastmod + Last-Modified header + footer copyright year + RSS/Atom pubDate and compute a freshness verdict: active (<6 months since last update), stale (6-18), abandoned (18-36), or unknown. Killer signal for web-design agencies pitching a rebuild (\"your site was last touched in 2019\"). Adds `freshness` to each row. Runs as a separate actor: https://apify.com/santamaria-automations/website-freshness-detector",
            "default": false
          },
          "enableJobBoardPresence": {
            "title": "Job Board Presence (LinkedIn Jobs, add-on)",
            "type": "boolean",
            "description": "For every place, look up open roles on LinkedIn Jobs and return aggregate hiring signals: open_roles_count, senior_roles_count, sample_titles, sample_locations, top_industry, avg_applicants, and a hiring_signal verdict (hot / active / quiet / no_roles / unknown). Prefers the LinkedIn company URL discovered by the LinkedIn Company Scraper add-on (exact company_id filter); falls back to a name-based search when no URL is available. Hot hiring is a strong outbound signal for staffing agencies, SaaS tools, and B2B services. Reuses the existing https://apify.com/santamaria-automations/linkedin-scraper -- billed per job result at $0.001.",
            "default": false
          },
          "googleApiKey": {
            "title": "Google API Key (PageSpeed Insights)",
            "type": "string",
            "description": "Your Google Cloud API key with the PageSpeed Insights API enabled. ONLY used by the PageSpeed Audit add-on above -- this is NOT an LLM API key. Free tier: 25,000 queries per day per Google Cloud project (no credit card required). Get a key in about 3 minutes: (1) Sign in at https://console.cloud.google.com and pick or create a project (skip the billing prompt -- PSI is free). (2) Open the API Library at https://console.cloud.google.com/apis/library, search for 'PageSpeed Insights API', click Enable. (3) Open Credentials at https://console.cloud.google.com/apis/credentials, click 'Create Credentials' -> 'API Key', copy the value. (4) Recommended: edit the key, restrict it to just the PageSpeed Insights API so a leaked key can't be abused. Paste the key here."
          },
          "pageSpeedStrategy": {
            "title": "PageSpeed Strategy",
            "enum": [
              "mobile",
              "desktop"
            ],
            "type": "string",
            "description": "Lighthouse audit strategy passed to PageSpeed Insights. Mobile is Google's own default and more relevant for local businesses.",
            "default": "mobile"
          },
          "enableChainDetection": {
            "title": "Detect Chains & Franchises (baked-in)",
            "type": "boolean",
            "description": "Tag places whose title matches a curated allowlist of ~60 well-known chains and franchises (McDonald's, Starbucks, Marriott, IKEA, Rewe, dm-drogerie, and more, plus DACH-specific entries). Adds a `chain` object to each row with `is_chain`, `chain_name`, `chain_category`, and a confidence score. Freelancers and agencies use this to filter out unsellable leads. Zero-fetch, no billing event.",
            "default": false
          },
          "enableContactExtraction": {
            "title": "Extract Contacts (add-on)",
            "type": "boolean",
            "description": "After scraping Maps, extract structured contact records (name, position, emails, phone numbers, LinkedIn) from each company's website using AI. Requires your own LLM API key below. Runs as a separate actor: https://apify.com/santamaria-automations/website-contact-extractor",
            "default": false
          },
          "enableJobExtraction": {
            "title": "Extract Job Listings (add-on)",
            "type": "boolean",
            "description": "After scraping Maps, extract job listings from each company's careers page using AI. Requires your own LLM API key below. Runs as a separate actor: https://apify.com/santamaria-automations/website-job-extractor",
            "default": false
          },
          "enableAiIcebreaker": {
            "title": "Generate AI Icebreaker Lines (add-on)",
            "type": "boolean",
            "description": "For every place, generate ONE personalized cold-outreach opening line referencing the business's actual details (rating, review count, category, city, and more). Uses your LLM key below. Base mode is zero-fetch. Runs as a separate actor: https://apify.com/santamaria-automations/ai-icebreaker",
            "default": false
          },
          "enableReviewIntelligence": {
            "title": "Review Intelligence LLM Analysis (add-on)",
            "type": "boolean",
            "description": "For every place with reviews, use an LLM to produce structured sentiment / complaint themes / praise themes / owner tone / red flags / opportunity signals from the user_reviews[] array. Complements the zero-fetch review_intel_math signals (which stay on automatically). Auto-enables includeReviews so the sub-actor has something to analyse. Uses your LLM key below. Runs as a separate actor: https://apify.com/santamaria-automations/review-intelligence-analyzer",
            "default": false
          },
          "enableIcebreakerEnriched": {
            "title": "Icebreaker Enriched Mode (fetch homepage)",
            "type": "boolean",
            "description": "When AI icebreaker is on, also fetch each place's homepage and pass a condensed summary to the LLM. Higher quality lines, higher per-place cost. Off by default.",
            "default": false
          },
          "icebreakerTone": {
            "title": "Icebreaker Tone",
            "enum": [
              "friendly",
              "professional",
              "casual",
              "direct"
            ],
            "type": "string",
            "description": "Voice for AI icebreaker lines. Applied only when the icebreaker add-on is enabled.",
            "default": "friendly"
          },
          "icebreakerFocus": {
            "title": "Icebreaker Focus (optional free-text)",
            "type": "string",
            "description": "Optional free-text guidance for the icebreaker prompt. Example: 'Focus on their photo count and their newest reviews', or 'Mention that we specialize in local SEO for care homes'. Passed to the LLM alongside the place record so every line reflects your outreach angle."
          },
          "enableBrowserFallback": {
            "title": "Browser Fallback for JS Sites",
            "type": "boolean",
            "description": "When contact or job extraction is enabled: automatically re-scrape websites that require JavaScript (React, Vue, Angular) with a full browser. Higher cost but catches ~25% more sites.",
            "default": false
          },
          "outputLanguage": {
            "title": "AI Enrichment Output Language",
            "type": "string",
            "description": "Language for AI-generated text fields (industry, description, positions, departments, icebreaker lines). Uses standard ISO 639-1 codes. Pass any ISO 639-1 language code: en, de, fr, ja, es, pt, it, ko, zh-CN, ar, nl, pl, sv, da, fi, no, cs, hu, ro, el, tr, th, vi, id, and more. Set to `auto` to match the website's own language.",
            "default": "en"
          },
          "geminiApiKey": {
            "title": "Gemini API Key (recommended)",
            "type": "string",
            "description": "Google Gemini Flash. Best quality/cost ratio, generous free tier. Get a key at https://aistudio.google.com/app/apikey. Heads up: this field is not masked in the Apify UI (technical limitation with cross-actor secret forwarding), use a test/scoped key if you're uncomfortable with that."
          },
          "groqApiKey": {
            "title": "Groq API Key (optional)",
            "type": "string",
            "description": "Groq. Ultra-fast inference. Used as fallback if Gemini key is also provided, or as primary if it's the only key. Get a key at https://console.groq.com/keys."
          },
          "openrouterApiKey": {
            "title": "OpenRouter API Key (optional)",
            "type": "string",
            "description": "OpenRouter. Access to 100+ models. Used as last fallback. Get a key at https://openrouter.ai/keys."
          },
          "llmModel": {
            "title": "LLM Model (optional override)",
            "type": "string",
            "description": "Override the default model used by whichever provider is selected. Defaults: Gemini `gemini-2.0-flash`, Groq `llama-3.3-70b-versatile`, OpenRouter `google/gemini-2.0-flash-001`. If your OpenRouter key doesn't have access to the paid Gemini model (returns 404), set this to something like `meta-llama/llama-3.1-8b-instruct` (free) or another model available on your account."
          },
          "waitForAddOns": {
            "title": "Merge Add-on Results into Places",
            "type": "boolean",
            "description": "When ON (default): the scraper waits for the enabled add-ons and merges their output into each place row, so you get ONE dataset with everything (contacts, jobs, emails, phones, socials, icebreaker line, and more). When OFF: add-ons run fire-and-forget in the background, you get the base places dataset plus separate add-on datasets that you have to join yourself. Ignored if no add-on is enabled.",
            "default": true
          },
          "addOnWaitCapMs": {
            "title": "Max Add-on Wait (ms)",
            "minimum": 60000,
            "maximum": 14400000,
            "type": "integer",
            "description": "Safety ceiling for how long the maps run stays alive waiting for add-ons before flushing remaining places with a timed_out status. Default 1800000 (30 min). Set higher for large batches, lower to fail fast.",
            "default": 1800000
          },
          "excludeCids": {
            "title": "Exclude CIDs",
            "type": "array",
            "description": "Google Maps CIDs to skip. Use this to exclude already-scraped places from results.",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "maxConcurrency": {
            "title": "Max Concurrency",
            "minimum": 1,
            "maximum": 20,
            "type": "integer",
            "description": "Maximum parallel HTTP requests",
            "default": 10
          },
          "requestDelay": {
            "title": "Request Delay (ms)",
            "minimum": 100,
            "maximum": 10000,
            "type": "integer",
            "description": "Delay between pagination requests in milliseconds",
            "default": 300
          },
          "proxyConfiguration": {
            "title": "Proxy Configuration",
            "type": "object",
            "description": "Apify proxy settings. Datacenter proxies work well and are cost-efficient.",
            "default": {
              "useApifyProxy": true
            }
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}