{
  "openapi": "3.0.1",
  "info": {
    "title": "Job Feed: 110+ Job Boards & Career Pages in 60+ Countries",
    "description": "One deduplicated, newest-first job feed from 110+ job boards in 60+ countries, 40+ ATS career systems and any company career page. Deepest in Switzerland, Germany and Austria. Daily new-jobs-only runs, radius filter, agency flag, and MCP for AI agents.",
    "version": "0.9",
    "x-build-id": "dpuywVgHEPRC7rjWF"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/santamaria-automations~job-feed/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-santamaria-automations-job-feed",
        "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~job-feed/runs": {
      "post": {
        "operationId": "runs-sync-santamaria-automations-job-feed",
        "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~job-feed/run-sync": {
      "post": {
        "operationId": "run-sync-santamaria-automations-job-feed",
        "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": {
          "countries": {
            "title": "Countries",
            "uniqueItems": true,
            "type": "array",
            "description": "Select country markets to activate their curated Tier 1 defaults. Supported: DE, AT, CH, UK (GB accepted as an alias for UK), US, CA, AU, BE, CZ, DK, ES, FR, GR, HR, HU, IE, IT, NL, NO, PL, PT, RO, RU, SE, SK, UA. For international aggregators (Indeed, LinkedIn, Jobrapido) or remote boards (Remotive, WWR, etc.) use the 'Platforms' field — they have no country-default set.",
            "items": {
              "type": "string",
              "enum": [
                "DE",
                "AT",
                "CH",
                "UK",
                "GB",
                "US",
                "CA",
                "AU",
                "BE",
                "CZ",
                "DK",
                "ES",
                "FR",
                "GR",
                "HR",
                "HU",
                "IE",
                "IT",
                "NL",
                "NO",
                "PL",
                "PT",
                "RO",
                "RU",
                "SE",
                "SK",
                "UA"
              ],
              "enumTitles": [
                "Germany (DE)",
                "Austria (AT)",
                "Switzerland (CH)",
                "United Kingdom (UK)",
                "United Kingdom (GB)",
                "United States (US)",
                "Canada (CA)",
                "Australia (AU)",
                "Belgium (BE)",
                "Czech Republic (CZ)",
                "Denmark (DK)",
                "Spain (ES)",
                "France (FR)",
                "Greece (GR)",
                "Croatia (HR)",
                "Hungary (HU)",
                "Ireland (IE)",
                "Italy (IT)",
                "Netherlands (NL)",
                "Norway (NO)",
                "Poland (PL)",
                "Portugal (PT)",
                "Romania (RO)",
                "Russia (RU)",
                "Sweden (SE)",
                "Slovakia (SK)",
                "Ukraine (UA)"
              ]
            }
          },
          "includeGlobalBoards": {
            "title": "Also search global boards (Indeed, Glassdoor, LinkedIn)",
            "type": "boolean",
            "description": "Also search Indeed, Glassdoor and LinkedIn in each selected country. Only applies when countries are set. Global boards you already listed in platforms are not added twice.",
            "default": true
          },
          "includeRegionalBoards": {
            "title": "Regional job boards",
            "enum": [
              "off",
              "nearby",
              "all"
            ],
            "type": "string",
            "description": "Off by default. Only applies when countries are set. 'Nearby' also searches the small regional boards (for example Jobbasel, Jobzueri, Ostjob, Carriera) whose canton contains your location. 'All' adds every healthy regional and specialist board of the selected countries. Needs a location that can be found in CH, DE, AT or LI for 'nearby'. Boards you already listed in platforms are not added twice.",
            "default": "off"
          },
          "platforms": {
            "title": "Platforms",
            "uniqueItems": true,
            "type": "array",
            "description": "Explicit platform IDs. ADDITIVE to `countries` (if you set countries=[DE,AT,CH] AND platforms=[wellfound-us], you get all DE/AT/CH Tier-1 defaults PLUS wellfound). Degraded / unvalidated platforms only run when named explicitly here. ★T1 marks Tier-1 platforms already covered by their country default set — no need to add them again if you already selected the country. Naming website-job-extractor and/or website-job-extractor-browser here also picks how companyUrls/searchUrls company pages are handled: only website-job-extractor -> HTTP only, no browser retry; only website-job-extractor-browser -> browser only; both, or neither (default) -> HTTP first with an automatic scoped browser retry. See the README's \"Company career pages\" section.",
            "items": {
              "type": "string",
              "enum": [
                "career-site-jobs",
                "ams-at",
                "karriere-at",
                "stepstone-at",
                "jobbank-ca",
                "arbeit-swiss",
                "jobs-ch",
                "jobscout24-ch",
                "arbeitsagentur-de",
                "jobware-de",
                "meinestadt-de",
                "stellenanzeigen-de",
                "stepstone-de",
                "nhs-jobs",
                "reed-uk",
                "usajobs-us",
                "wellfound-us",
                "workatastartup-us",
                "website-job-extractor",
                "website-job-extractor-browser",
                "westjob-at",
                "seek",
                "ictjobs-ch",
                "jobbasel-ch",
                "jobbern-ch",
                "jobmittelland-ch",
                "jobzueri-ch",
                "myjob-ch",
                "ostjob-ch",
                "schaffu-ch",
                "sozjobs-ch",
                "swissdevjobs-ch",
                "zentraljob-ch",
                "nicejob-de",
                "stellenmarkt-de",
                "jobindex-dk",
                "finn-no",
                "infojobs-es",
                "france-travail",
                "welcome-to-the-jungle",
                "naukri",
                "computrabajo",
                "idealist",
                "indeed",
                "jobrapido",
                "linkedin",
                "pracuj-pl",
                "justjoinit",
                "builtin",
                "cryptojobslist",
                "dice",
                "e-fellows",
                "remoteok",
                "remotive",
                "web3career",
                "weworkremotely",
                "arbetsformedlingen-se",
                "charityjob-uk",
                "escape-the-city",
                "guardianjobs-uk",
                "jobs-ac-uk",
                "jobserve-uk",
                "targetjobs-uk",
                "teaching-vacancies-uk",
                "tes-uk",
                "totaljobs-uk",
                "healthecareers-us",
                "levels-fyi-us",
                "rigzone-us",
                "wayup-us",
                "sepe-es",
                "hh-ru",
                "trudvsem-ru",
                "subito-it-jobs",
                "werk-nl",
                "nationale-vacaturebank-nl",
                "irishjobs-ie",
                "hellowork-fr",
                "kariera-gr",
                "net-empregos-pt",
                "profesia-sk",
                "prace-cz",
                "profession-hu",
                "anofm-ro",
                "work-ua",
                "dcz-gov-ua",
                "mojposao-hr",
                "vdab-be",
                "forem-be",
                "snagajob-us",
                "craigslist-jobs",
                "dribbble-jobs",
                "biospace",
                "higheredjobs",
                "nofluffjobs-eu",
                "praca-gov-pl",
                "carriera-ch",
                "jobup-ch",
                "glassdoor",
                "cwjobs-uk",
                "ejobs-ro",
                "ycombinator",
                "efinancialcareers",
                "michaelpage-intl",
                "euraxess",
                "alpha-topjobs-ch",
                "lavoro-cdt-ch",
                "ge-ch-emploi",
                "prospects-uk",
                "milkround-uk",
                "hays-uk",
                "jobkorea-kr",
                "bayt-me"
              ],
              "enumTitles": [
                " career-site-jobs — career-site-jobs  ★T1",
                "🇦🇹 ams-at — ams.at  ★T1",
                "🇦🇹 karriere-at — karriere.at  ★T1",
                "🇦🇹 stepstone-at — stepstone.at  ★T1",
                "🇨🇦 jobbank-ca — jobbank.gc.ca  ★T1",
                "🇨🇭 arbeit-swiss — arbeit.swiss  ★T1",
                "🇨🇭 jobs-ch — jobs.ch  ★T1",
                "🇨🇭 jobscout24-ch — jobscout24.ch  ★T1",
                "🇩🇪 arbeitsagentur-de — arbeitsagentur.de  ★T1",
                "🇩🇪 jobware-de — jobware.de  ★T1",
                "🇩🇪 meinestadt-de — meinestadt.de  ★T1",
                "🇩🇪 stellenanzeigen-de — stellenanzeigen.de  ★T1",
                "🇩🇪 stepstone-de — stepstone.de  ★T1",
                "🇬🇧 nhs-jobs — jobs.nhs.uk  ★T1",
                "🇬🇧 reed-uk — reed.co.uk  ★T1",
                "🇺🇸 usajobs-us — usajobs.gov  ★T1",
                "🇺🇸 wellfound-us — wellfound.com  ★T1",
                "🇺🇸 workatastartup-us — workatastartup.com  ★T1",
                " website-job-extractor — website-job-extractor",
                " website-job-extractor-browser — website-job-extractor-browser",
                "🇦🇹 westjob-at — westjob.at",
                "🇦🇺 seek — seek.com.au  ★T1",
                "🇨🇭 ictjobs-ch — ictjobs.ch",
                "🇨🇭 jobbasel-ch — jobbasel.ch",
                "🇨🇭 jobbern-ch — jobbern.ch",
                "🇨🇭 jobmittelland-ch — jobmittelland.ch",
                "🇨🇭 jobzueri-ch — jobzueri.ch",
                "🇨🇭 myjob-ch — myjob.ch",
                "🇨🇭 ostjob-ch — ostjob.ch",
                "🇨🇭 schaffu-ch — schaffu.ch",
                "🇨🇭 sozjobs-ch — sozjobs.ch",
                "🇨🇭 swissdevjobs-ch — swissdevjobs.ch",
                "🇨🇭 zentraljob-ch — zentraljob.ch",
                "🇩🇪 nicejob-de — nicejob.de",
                "🇩🇪 stellenmarkt-de — stellenmarkt.de",
                "🇩🇰 jobindex-dk — jobindex.dk  ★T1",
                "🇳🇴 finn-no — finn.no  ★T1",
                "🇪🇸 infojobs-es — infojobs.net  ★T1",
                "🇫🇷 france-travail — francetravail.fr  ★T1",
                "🇫🇷 welcome-to-the-jungle — welcometothejungle.com  ★T1",
                "🇮🇳 naukri — naukri.com",
                "🌍 computrabajo — computrabajo.com",
                "🌍 idealist — idealist.org",
                "🌍 indeed — indeed.com (HTTP)",
                "🌍 jobrapido — jobrapido.com",
                "🌍 linkedin — linkedin.com",
                "🇵🇱 pracuj-pl — pracuj.pl  ★T1",
                "🇵🇱 justjoinit — justjoin.it  ★T1",
                "🌐 builtin — builtin.com",
                "🌐 cryptojobslist — cryptojobslist.com",
                "🌐 dice — dice.com",
                "🌐 e-fellows — e-fellows.net",
                "🌐 remoteok — remoteok.com",
                "🌐 remotive — remotive.com",
                "🌐 web3career — web3.career",
                "🌐 weworkremotely — weworkremotely.com",
                "🇸🇪 arbetsformedlingen-se — arbetsformedlingen.se  ★T1",
                "🇬🇧 charityjob-uk — charityjob.co.uk",
                "🇬🇧 escape-the-city — escapethecity.org",
                "🇬🇧 guardianjobs-uk — jobs.theguardian.com",
                "🇬🇧 jobs-ac-uk — jobs.ac.uk",
                "🇬🇧 jobserve-uk — jobserve.com",
                "🇬🇧 targetjobs-uk — targetjobs.co.uk",
                "🇬🇧 teaching-vacancies-uk — teaching-vacancies.service.gov.uk",
                "🇬🇧 tes-uk — tes.com",
                "🇬🇧 totaljobs-uk — totaljobs.com",
                "🇺🇸 healthecareers-us — healthecareers.com",
                "🇺🇸 levels-fyi-us — levels.fyi",
                "🇺🇸 rigzone-us — rigzone.com",
                "🇺🇸 wayup-us — wayup.com",
                "🇪🇸 sepe-es — empleate.gob.es  ★T1",
                "🇷🇺 hh-ru — hh.ru  ★T1",
                "🇷🇺 trudvsem-ru — trudvsem.ru  ★T1",
                "🇮🇹 subito-it-jobs — subito.it  ★T1",
                "🇳🇱 werk-nl — werk.nl  ★T1",
                "🇳🇱 nationale-vacaturebank-nl — nationalevacaturebank.nl  ★T1",
                "🇮🇪 irishjobs-ie — irishjobs.ie  ★T1",
                "🇫🇷 hellowork-fr — hellowork.com  ★T1",
                "🇬🇷 kariera-gr — kariera.gr  (EL keyword required)  ★T1",
                "🇵🇹 net-empregos-pt — net-empregos.com  ★T1",
                "🇸🇰 profesia-sk — profesia.sk  ★T1",
                "🇨🇿 prace-cz — prace.cz  ★T1",
                "🇭🇺 profession-hu — profession.hu  ★T1",
                "🇷🇴 anofm-ro — anofm.ro  (RO keyword required)  ★T1",
                "🇺🇦 work-ua — work.ua",
                "🇺🇦 dcz-gov-ua — dcz.gov.ua  ★T1",
                "🇭🇷 mojposao-hr — mojposao.hr  ★T1",
                "🇧🇪 vdab-be — vdab.be  ★T1",
                "🇧🇪 forem-be — leforem.be  ★T1",
                "🇺🇸 snagajob-us — snagajob.com",
                "🇺🇸 craigslist-jobs — craigslist.org",
                "🇺🇸 dribbble-jobs — dribbble.com",
                "🇺🇸 biospace — jobs.biospace.com",
                "🇺🇸 higheredjobs — higheredjobs.com",
                "🇵🇱 nofluffjobs-eu — nofluffjobs.com  ★T1",
                "🇵🇱 praca-gov-pl — praca.gov.pl",
                "🇨🇭 carriera-ch — carriera.ch",
                "🇨🇭 jobup-ch — jobup.ch",
                "🌍 glassdoor — glassdoor.com  (see README for per-result pricing)",
                "🇬🇧 cwjobs-uk — cwjobs.co.uk",
                "🇷🇴 ejobs-ro — ejobs.ro  ★T1",
                "🌍 ycombinator — news.ycombinator.com  (HN job board submissions)",
                "🌍 efinancialcareers — efinancialcareers.com",
                "🌍 michaelpage-intl — michaelpage.com",
                "🌍 euraxess — euraxess.ec.europa.eu",
                "🇨🇭 alpha-topjobs-ch — alpha.ch / topjobs.ch",
                "🇨🇭 lavoro-cdt-ch — lavoro.cdt.ch",
                "🇨🇭 ge-ch-emploi — ge.ch",
                "🇬🇧 prospects-uk — prospects.ac.uk  (graduate/placement jobs)",
                "🇬🇧 milkround-uk — milkround.com",
                "🇬🇧 hays-uk — hays.com",
                "🇰🇷 jobkorea-kr — jobkorea.co.kr",
                "🌍 bayt-me — bayt.com"
              ]
            }
          },
          "keywords": {
            "title": "Keywords",
            "type": "array",
            "description": "Search terms. Each keyword is forwarded to every selected platform. Results deduplicated across keywords AND platforms.",
            "items": {
              "type": "string"
            }
          },
          "titleFilter": {
            "title": "Title filter",
            "type": "string",
            "description": "Comma-separated list of title substrings, case-insensitive OR match. Only keep jobs whose title contains at least one of the terms. Example: sales manager, account executive. Leave empty to receive all results (no filter). For platforms that natively support title filtering (stepstone-de), the filter is forwarded to the sub-actor directly (applied before detail-fetch, no extra cost). For all other platforms the orchestrator applies it client-side after receiving results."
          },
          "location": {
            "title": "Location",
            "type": "string",
            "description": "City, region, or state. Forwarded to each platform in the format it accepts. A handful of platforms declare location as a closed list rather than free text (e.g. swissdevjobs-ch only accepts \"Zurich\", not \"Zürich\"); for those, job-feed matches your value case-insensitively and accent-folded against the platform's own list (Zürich -> Zurich, Genève -> Geneva) before forwarding. If nothing matches, that platform's location filter is skipped (not the whole platform) and a warning is logged — you still get results, just unfiltered by location for that one platform."
          },
          "radiusKm": {
            "title": "Radius (km)",
            "minimum": 0,
            "maximum": 200,
            "type": "integer",
            "description": "Search radius in km. Silently clamped per platform if it exceeds that platform's max.",
            "default": 25
          },
          "sortBy": {
            "title": "Sort order",
            "enum": [
              "",
              "newest",
              "relevance",
              "salary"
            ],
            "type": "string",
            "description": "Controls the order platforms return results. Forwarded to each sub-actor using the field name it declares (sortBy or sortOrder). Canonical values:\n• (empty) — \"Platform default\": job-feed forwards NO sort field at all; the sub-actor's own default ordering applies. Use this for platforms whose declared sort enum has drifted from job-feed's registry (rare, self-heals via the strip-and-retry guard) or when you simply don't care about order.\n• newest (default) — most recently posted first. Best for scheduled scrapes so fresh listings surface immediately.\n• relevance — platform’s own relevance ranking for your keywords.\n• salary — highest-paying first (only on platforms that support salary sort). Platforms that don’t recognise the value silently ignore it.",
            "default": "newest"
          },
          "postedWithinDays": {
            "title": "Posted within (days)",
            "minimum": 0,
            "maximum": 365,
            "type": "number",
            "description": "Only include listings posted within this window. Accepts fractional values for sub-day precision: 0.042 ≈ 1 hour (use 1.0/24 for exactly 1 hour), 0.5 = 12 hours, 1 = 24 hours, 30 = one month. 0 = no filter. For platforms that support server-side age filtering, the value is forwarded directly (rounded up to the nearest hour or day as the platform requires). For platforms without native age filtering, the orchestrator drops items whose posted_date is older than this window after normalization.",
            "default": 0
          },
          "includeCareerSites": {
            "title": "Include ATS / career sites (40+ supported)",
            "type": "boolean",
            "description": "Also fetch listings from Greenhouse, Lever, Workday, Ashby, Personio, and 20 other ATS platforms via career-site-jobs-scraper. Requires companyUrls (company career-page URLs) -- this extractor has no keyword-search mode, so keywords alone cannot drive it; add companyUrls or pick job boards via countries/platforms instead. For non-ATS company URLs (handled separately via an LLM extractor), keywords narrow the results already found on those pages rather than searching for them.",
            "default": false
          },
          "companyUrls": {
            "title": "Company URLs",
            "type": "array",
            "description": "Fetch jobs from these company career pages. One URL per company. URLs on a known job system (Greenhouse, Workday, Lever, ...) go straight to career-site-jobs (cheapest, no browser or LLM). Everything else goes through website-job-extractor and/or website-job-extractor-browser -- which one depends on `platforms`: only website-job-extractor selected there -> HTTP only, no browser retry; only website-job-extractor-browser selected -> browser only; both selected, or neither -- the default -- -> HTTP first, with an automatic scoped browser retry only for the companies HTTP couldn't read. See the README's \"Company career pages\" section for the full mode table. Already know a company's job system from a previous run's `next_run_input`? Use `careerSites` instead -- it skips this detection step and is cheaper (about $0.001/job vs about $0.012/job through the managed extractor). If career-site-jobs cannot read a company, job-feed falls back to the extractor in the same run (see csjFallbackToExtractor). Via the API, items may also be objects {\"url\", \"country\", \"company\", \"ref\"} (country is an optional ISO 3166-1 alpha-2 default; company is an optional label; ref is an optional string of up to 200 characters that is echoed unchanged as company.ref on every row of that URL, in input_refs[].ref and as ref on company_hiring rows).",
            "items": {
              "type": "string"
            }
          },
          "careerSites": {
            "title": "Career sites on a known job system",
            "type": "array",
            "description": "Company career pages whose job system (ATS) you already know -- sent straight to career-site-jobs, skipping the detection step companyUrls goes through. Each item is either a plain URL (career-site-jobs auto-detects the platform) or {\"url\": \"...\", \"ats\": \"...\", \"company\": \"...\"} naming the ATS and (optionally) the company explicitly. Supported ats values: adp, ashby, avature, bamboohr, brassring, comeet, eightfold, greenhouse, icims, jazzhr, join, lever, oracle_recruiting (or oracle), personio, phenom, pinpoint, recruitee, rippling, smartrecruiters, successfactors_rmk (or successfactors), talentbrew, taleo, teamtailor, workable, workday. An unrecognized or missing ats falls back to website-job-extractor with a warning rather than being dropped. company is an optional label or domain (e.g. \"oracle.com\") used for the company's display name and url/domain on both job rows and zero-job rows -- set it when the URL's own host would otherwise produce a misleading name (an Oracle Recruiting Cloud tenant host reads as \"Eeho\" without it). The easiest way to fill this in: run companyUrls once, then copy the `next_run_input.careerSites` value from the OUTPUT record into this field for every later run against the same companies -- career-site-jobs costs about $0.001/job versus roughly $0.012/job (managed) through the extractor; the OUTPUT record now fills in company (and the original website) automatically. If career-site-jobs cannot read an entry, job-feed retries it with the extractor in the same run so no jobs are lost (turn off with csjFallbackToExtractor), and a structurally broken entry is moved back to companyUrls in next_run_input. An entry may also carry an optional website (the company's original site), used only for that fallback. An entry may also carry an optional employer, for a shared group board where several employers list on one URL (for example vitrea-gesundheit.onlyfy.jobs): career-site-jobs then keeps only that employer's jobs, and two entries with the same url but different employers are both read. Optional country (ISO 3166-1 alpha-2, e.g. \"CH\") sets a default country for career-site-jobs rows whose location cannot be resolved, useful for single-country tenants; rows with a known other country are still dropped."
          },
          "companyList": {
            "title": "Company list (built-in directory)",
            "type": "object",
            "description": "Pick employers from the built-in company directory instead of listing URLs. Object with optional filters: regions (ch-de, de), industries, subIndustries, countries (CH, DE), headcount (1000+, 250-1000, 50-250, <50, unknown) and limit (default 50, max 300). All filters are combined with AND, values inside one list with OR; an empty object, or one matching nothing, is ignored with a warning if other inputs select platforms, else the run ends unbilled. Example: {\"regions\": [\"ch-de\"], \"industries\": [\"biotech\"], \"limit\": 50}. Cost: lookup free, normal sub-actor price per company."
          },
          "includeJobDetails": {
            "title": "Fetch full job details",
            "type": "boolean",
            "description": "When ON, each result is enriched with full description, salary, requirements from the platform's detail page. Cost impact varies by platform: arbeitsagentur-de detail is $20/1k (vs $8/1k SERP), meinestadt-de and jobware-de are ~$8.50/1k detail. Flat-rate platforms (ams-at, arbeit-swiss, linkedin) are unaffected. With companyUrls or careerSites, ON also reads each posting's employer page, not only board detail pages: the website extractor opens it, stores the posting text in description_md plus structured fields such as salary, deadline, contact and workload, and bills its job-detail-result event per posting (billed per posting once priced). Leave OFF unless description text is required.",
            "default": false
          },
          "detailCountries": {
            "title": "Detail pages only for countries",
            "type": "array",
            "description": "Optional list of ISO 3166-1 alpha-2 country codes (for example CH, DE). Only used with includeJobDetails. Sent to career-site-jobs, which then reads detail pages only for rows whose country is in the list; other rows are still returned and charged, just without the detail page. Codes are uppercased; entries that are not 2 letters are ignored with a warning. Leave empty to read details for every row (default).",
            "items": {
              "type": "string"
            }
          },
          "maxResultsPerCompany": {
            "title": "Max jobs per career site",
            "minimum": -1,
            "type": "integer",
            "description": "Per company or career site (companyUrls, careerSites). -1 = every job of each site (career-site-jobs pages the whole list up to its hard limit of 5000 jobs per company; the website extractor up to 10,000). A positive number caps each company at that many jobs and replaces the share derived from maxResultsPerPlatform or maxResultsTotal. 0 or absent keeps the current behaviour: those caps are divided across the companies, and with no caps career-site-jobs stops at its own default of 500 jobs per company.",
            "default": 0
          },
          "includeContactData": {
            "title": "Include recruiter contact data",
            "type": "boolean",
            "description": "When ON, populates output field `contacts[]` (per-job recruiter contacts: salutation, first_name, last_name, email, phone, position) and, for dice results, `company.recruiters[]` (company-level recruiter roster). Roughly 28 of our 50 platforms surface per-job contact fields on the detail page. IMPLIES includeJobDetails, since contact info lives on the detail page.",
            "default": false
          },
          "enableBrowserFallback": {
            "title": "Enable browser fallback (legacy -- use platforms instead)",
            "type": "boolean",
            "description": "Deprecated 2026-10-03, kept only so old saved inputs keep working. The browser-retry behavior this used to turn on/off is now selected via `platforms`: name only website-job-extractor for HTTP-only (no browser retry), only website-job-extractor-browser to send company pages straight to a browser, both (or neither -- the new default) for HTTP first with an automatic scoped browser retry. See the README's \"Company career pages\" section. If set, `true` forces the HTTP-first-with-retry behavior regardless of `platforms`; `false` or omitted is ignored -- the platforms-based rule above decides on its own."
          },
          "includeCompanyDetails": {
            "title": "Include rich company details",
            "type": "boolean",
            "description": "When ON, opts sub-actors into the second-tier company-profile fetch. Populates rich `company.*` slots when the platform emits them: about, industry, size_range, phone, email, headquarters/address, social_urls (LinkedIn/Facebook/Twitter/Instagram/YouTube/TikTok/Xing/GitHub/Kununu/Glassdoor), active_jobs_count, active_jobs[], plus a platform_extras passthrough for platform-specific fields (e.g. LinkedIn follower_count, Glassdoor rating). Roughly 28 of our sub-actors accept `includeCompanyDetails`; 5 older ones (dice, google-jobs, etc.) accept `includeCompanyInfo` — both are forwarded. IMPLIES includeJobDetails. Adds one extra fetch per unique company, so cost impact depends on how many distinct employers appear in your results.",
            "default": false
          },
          "csjFallbackToExtractor": {
            "title": "Fall back to the extractor when career-site-jobs fails",
            "type": "boolean",
            "description": "When ON (default), a companyUrls/careerSites company that career-site-jobs cannot read (invalid query, board not found, unsupported platform, blocked, parse error, connection error, failed sub-run) is retried once with website-job-extractor in the same run, so its jobs are not lost. career-site-jobs is cheaper (about $0.001/job vs about $0.012/job managed), the fallback only costs extractor rates for companies it actually rescues. Timed-out companies are never retried. Turn OFF to only list such companies in run_summary.companies_not_read.",
            "default": true
          },
          "handoverSharedBoards": {
            "title": "Hand shared group boards to career-site-jobs",
            "type": "boolean",
            "description": "When ON (default), the website extractor does not read a shared group board itself (for example a hospital group's onlyfy board that lists several employers). It reports the board and the employer instead, and job-feed reads that employer's jobs with career-site-jobs in the same run. Turn OFF to let the extractor read such boards directly.",
            "default": true
          },
          "sameRunHandover": {
            "title": "Read extractor handovers in the same run",
            "type": "boolean",
            "description": "When ON (default), a company the website extractor recognises as sitting on a job system career-site-jobs can read (and finds 0 jobs on) is handed to career-site-jobs in the same run, so its jobs are not delayed to the next run. Companies already retried by csjFallbackToExtractor are never handed back. Turn OFF to only record the handover in next_run_input.",
            "default": true
          },
          "includeFullPostingText": {
            "title": "Include full posting text",
            "type": "boolean",
            "description": "Alias of includeJobDetails for company pages read by the website extractor: true sends includeJobDetails=true to the extractor (posting text incl. PDF postings in description_md, plus structured detail fields; longer runs, paid job-detail event per job). Sent only when true.",
            "default": false
          },
          "maxFullTextChars": {
            "title": "Max full-text characters",
            "minimum": 500,
            "maximum": 50000,
            "type": "integer",
            "description": "Only with includeJobDetails (or includeFullPostingText). Maximum characters of posting text stored in description_md per job (500 to 50000). Longer texts are cut at a paragraph boundary. Sent to the extractor only when set.",
            "default": 12000
          },
          "fullTextLlmFill": {
            "title": "LLM fill of location and date from posting text",
            "type": "boolean",
            "description": "Only with includeJobDetails (or includeFullPostingText). On (default): when a job's location, posting date or similar detail is still missing after the posting text was read, one LLM call fills it. Off: the text is still read but no LLM call is made for it. Sent to the extractor only when set.",
            "default": true
          },
          "includeCompaniesWithoutJobs": {
            "title": "Include zero-job company rows",
            "type": "boolean",
            "description": "When ON (default), companyUrls/careerSites companies whose career site was read successfully but had no jobs matching your filters (or none open at all) still get one dataset row (`_type: company_no_matching_jobs`) -- a useful signal on its own, e.g. a funded company with no postings yet. Never charged: you only pay the company fee for the read, same as always, and these rows never count toward orchestrator_billed_events. Turn OFF for job rows only. See README \"Zero-job company rows\".",
            "default": true
          },
          "outputMode": {
            "title": "Output mode",
            "enum": [
              "jobs",
              "companies"
            ],
            "type": "string",
            "description": "jobs (default): one dataset row per job. companies: one `company_hiring` row per companyUrls entry (hiring_status hiring, no_open_roles or not_read, hiring_open_roles_count, hiring_roles, hiring_sources, hiring_jobs_url) and no job rows. In companies mode only companyUrls are read (other sources are ignored with a warning), includeCompaniesWithoutJobs is implied, onlyNewJobs and trackJobLifecycle are ignored, and the usual per-job event is still charged once per unique role read (up to maxResultsPerCompany per company, at most 50); the company row itself is free. Send `ref` on each companyUrls object to merge rows back to your own key. See the README section \"Company hiring signals\".",
            "default": "jobs"
          },
          "hiringBrowserFallback": {
            "title": "Browser retry for JS-rendered career sites (companies mode)",
            "type": "boolean",
            "description": "Companies mode only. Retry career sites that need a browser (JS-rendered). Off by default because a browser read costs about $0.18 per place in your account versus about $0.01-0.03 for normal reads. When off, those places get hiring_status not_read with not_read_reason needs_browser and nothing is charged. Ignored when outputMode is jobs.",
            "default": false
          },
          "hiringAtsViaCareerSites": {
            "title": "Read known job systems via career-site-jobs (companies mode)",
            "type": "boolean",
            "description": "Companies mode only. When a company website uses a known job system, read it directly through career-site-jobs instead of the AI extractor (cheaper, exact titles). Off by default while we measure it.",
            "default": false
          },
          "dedupMode": {
            "title": "Dedup mode: streaming (default) or batch",
            "enum": [
              "streaming",
              "batch"
            ],
            "type": "string",
            "description": "How cross-platform duplicates are surfaced.\n\n• streaming (default): rows flow to the dataset AS EACH platform finishes. Each row carries the ONE platform that first delivered it (first-arriver wins). Duplicates that arrive later are recorded in the terminal `sources_manifest` item under `additional_sources_by_job_id[job_id]`. Best for real-time consumers, cost-abort semantics (you pay only for delivered rows), and fastest time-to-first-result.\n\n• batch: rows are buffered until EVERY sub-actor completes, then emitted ONCE per unique job with `sources[]` containing every platform that reported it. Cross-source origins live inside each row — no manifest join required. Best for one-shot pipelines that don't want to reassemble the manifest downstream. Tradeoff: no partial delivery on abort, longer time-to-first-result, higher orchestrator memory footprint.\n\nPPE billing is identical in both modes: exactly one event per unique job_id.",
            "default": "streaming"
          },
          "onlyNewJobs": {
            "title": "Only new jobs (skip already delivered)",
            "type": "boolean",
            "description": "Off by default. When on, jobs that an earlier run already delivered are not pushed and not charged the job-feed fee. Job-feed keeps a list of delivered job IDs in a named key-value store on your own account. Repeats still cost you the sub-actor fees, because the platforms run before job-feed knows a job is old, so keep postedWithinDays set as the main cost control. Runs that share a store name share the list.",
            "default": false
          },
          "companySummary": {
            "title": "Company hiring summary (free)",
            "type": "boolean",
            "description": "Off by default, no extra cost. When on, job-feed writes a per-company summary (open roles, boards, top countries and cities, roles by function and seniority, posting dates) to the run's key-value store only: top 200 in the OUTPUT record under company_summary, up to 5,000 in the COMPANY_SUMMARY record. No dataset rows are added. Example: true.",
            "default": false
          },
          "companySummaryStoreName": {
            "title": "Company summary history store",
            "type": "string",
            "description": "Only used with Company hiring summary. Name of a key-value store on your account that keeps open roles per company for each run (up to 90 runs), so each company gets a trend with the change since the last run. Empty means no trend. Example: my-hiring-trends."
          },
          "seenJobsStoreName": {
            "title": "Seen-jobs store name",
            "type": "string",
            "description": "Only used with Only new jobs or Track job lifecycle. Name of the key-value store that remembers delivered job IDs and job history. Leave empty to get job-feed-seen-<hash> derived from your search settings, so the same schedule always reuses the same store. Set it to share one list across several schedules."
          },
          "seenJobsTtlDays": {
            "title": "Seen-jobs memory (days)",
            "minimum": 1,
            "maximum": 180,
            "type": "integer",
            "description": "Only used with Only new jobs. A delivered job is skipped for this many days, then delivered again if it is still listed. Between 1 and 180.",
            "default": 30
          },
          "trackJobLifecycle": {
            "title": "Track job lifecycle across runs",
            "type": "boolean",
            "description": "Off by default. Use on scheduled runs with the same input. Each row gets lifecycle {first_seen_at, last_seen_at, days_online, runs_seen} and OUTPUT lists closed_jobs (seen last run, missing from a complete, uncapped run of the same search; capped or partial runs skip closed detection). Free; history is kept in the Seen-jobs store on your account. Example: {\"trackJobLifecycle\": true, \"seenJobsStoreName\": \"my-ch-data-jobs\"}.",
            "default": false
          },
          "minRelevanceScore": {
            "title": "Minimum relevance score",
            "minimum": 0,
            "maximum": 100,
            "type": "integer",
            "description": "Drop rows whose title doesn't match your keywords well enough. Each keyword is scored separately (fraction of its tokens, case-insensitive and umlaut-folded, present in the title) and the row's score is that of the best-matching keyword. 0 = keep everything (default, no filtering). 50 = drop rows where fewer than half of the best-matching keyword's tokens are in the title (removes clearly off-topic hits like 'Preventive Medicine Officer' from a Software Engineer query on a healthcare board). 100 = only keep rows where EVERY token of at least one keyword appears. Values are per-cent so leave at 0 unless you want filtering. The unfiltered dataset always gets a per-platform relevance report as a terminal item so you can decide which platforms are worth keeping.",
            "default": 0
          },
          "excludeAgencies": {
            "title": "Exclude staffing agencies",
            "type": "boolean",
            "description": "Off by default. When on, rows whose company is a staffing or recruiting agency (company.is_agency = true) are dropped before they are pushed or charged the job-feed fee. Agencies come from a DACH registry of Swiss, German and Austrian staffing, executive search and job-aggregator firms (high and medium confidence only), plus a name check for words like Zeitarbeit, Personalvermittlung and Personalberatung. Firms that only hold a staffing licence (agency_confidence = licence_only) are never dropped. The number dropped is reported as agencies_excluded in the run summary (OUTPUT record).",
            "default": false
          },
          "enforceRadius": {
            "title": "Enforce search radius",
            "type": "boolean",
            "description": "On by default. Active only when location is set and radiusKm is above 0. Some boards ignore the radius, so rows clearly farther than radiusKm (plus a margin of 10% or 3 km, whichever is larger) from your location are dropped before they are charged. Rows with no city, an unknown city, only a region, canton or country, or remote jobs are always kept. If the location cannot be found the filter is skipped. The result is reported as radius_filter in the run summary (OUTPUT record).",
            "default": true
          },
          "searchUrls": {
            "title": "Direct search URLs (advanced)",
            "type": "array",
            "description": "Alternative to keywords + platforms. Paste search-result URLs from any supported platform; the feed routes each to the correct sub-actor by host. Unknown hosts fall back to website-job-extractor with a notice.",
            "items": {
              "type": "string",
              "pattern": "^https?://"
            }
          },
          "jobUrls": {
            "title": "Direct job URLs",
            "maxItems": 500,
            "type": "array",
            "description": "Single job posting URLs (max 500) for an alive check plus full data. Routed by host to boards with detail-URL support (now: SEEK incl. JobStreet/JobsDB, Idealist); others are listed as unsupported and not charged. Alone it runs no keyword search. Rows carry job_status (open/expired/unknown).",
            "items": {
              "type": "string",
              "pattern": "^https?://"
            }
          },
          "maxResultsPerPlatform": {
            "title": "Max results per platform",
            "minimum": 0,
            "type": "integer",
            "description": "How the three result caps interact (evaluated in this order): (1) maxResultsPerQueryPerPlatform limits results PER KEYWORD on a given platform; (2) this field (maxResultsPerPlatform) limits total RAW results per platform across all its keywords, before cross-platform dedup; (3) maxResultsTotal limits the final UNIQUE job count across ALL platforms combined, after dedup — once hit, no further platform results are accepted or billed. All three default to 0 = no job-feed-side cap (each sub-actor's own default applies, typically 50-200). If maxResultsPerQueryPerPlatform is set and this field is 0, the effective per-platform total is derived as maxResultsPerQueryPerPlatform × keyword-count. Alias: `maxResults` is accepted as a synonym for this field when this field is left at 0 (matches the field name several sub-actors use directly).",
            "default": 0
          },
          "maxResultsPerQueryPerPlatform": {
            "title": "Max results per query per platform",
            "minimum": 0,
            "type": "integer",
            "description": "Per-keyword result cap forwarded to each sub-actor — the FIRST cap applied (see maxResultsPerPlatform for how all three caps interact). When set to a positive integer, overrides Max results per platform as the per-query cap sent to sub-actors. Use this when you run multiple keywords and want a tighter cap per keyword (e.g. 10 results per keyword x 5 keywords = 50 max per platform). 0 = fall back to maxResultsPerPlatform. Alias: `maxResultsPerQuery` is accepted as a synonym for this field when this field is left at 0 — added after a run sent `maxResultsPerQuery: 3` (not a real field name) and got silently ignored, returning far more results than expected.",
            "default": 0
          },
          "maxResultsTotal": {
            "title": "Max unique results total",
            "minimum": 0,
            "type": "integer",
            "description": "Cap on unique jobs emitted after cross-platform dedup — the LAST and outermost of the three caps (see maxResultsPerPlatform for how they interact). 0 = unlimited. This is the number the orchestrator event bills on: once this many unique jobs have been delivered, job-feed stops accepting further unique jobs from any platform (already-running sub-actor calls still finish, but their extra results are dropped and never billed). A warning is logged once when the cap is reached.",
            "default": 0
          },
          "perHostConcurrency": {
            "title": "Per-host concurrency (advanced)",
            "minimum": 1,
            "maximum": 6,
            "type": "integer",
            "description": "Max concurrent sub-actor runs sharing the same host. Prevents cross-actor rate-limit collisions.",
            "default": 2
          },
          "globalConcurrency": {
            "title": "Global concurrency (advanced, legacy)",
            "minimum": 0,
            "maximum": 16,
            "type": "integer",
            "description": "Legacy name for the same in-flight cap as maxParallelPlatforms. Leave at 0 (default) to let maxParallelPlatforms govern alone. Set this to a positive value only if you want a stricter cap than maxParallelPlatforms for an existing saved input: when both are set, the lower of the two wins. New integrations should use maxParallelPlatforms instead.",
            "default": 0
          },
          "maxParallelPlatforms": {
            "title": "Max parallel platforms (advanced)",
            "minimum": 1,
            "maximum": 32,
            "type": "integer",
            "description": "Caps how many sub-actor runs job-feed keeps in flight at once. Remaining platforms queue until a slot frees. Protects against Apify's account-wide concurrent-runs-limit-exceeded error (shared across every actor/run on the account, not just this job-feed run) -- a start that still hits the limit is retried automatically with backoff before the platform is marked failed. Combined with globalConcurrency: the stricter (lower) of the two wins only if you set globalConcurrency to a positive value.",
            "default": 8
          },
          "maxTotalMemoryMbytes": {
            "title": "Max total sub-actor memory (MB, advanced)",
            "minimum": 0,
            "maximum": 65536,
            "type": "integer",
            "description": "Total RAM budget the orchestrator is allowed to consume across all concurrent sub-actor runs. Sub-actors that don't fit queue and start as running ones finish, largest queued request first. Leave at 0 to use the 4096 MB default, which fits every Apify plan including Free (8 GB). Set a lower value to keep RAM free for other work on the same account (another job-feed run, an unrelated actor, a scheduled task), or a higher one if your plan has more memory and you want more sub-actors running in parallel. Per-platform RAM needs vary: lean Go HTTP actors ~128-256 MB, detail-mode actors ~512 MB, Camoufox browser actors 1024-4096 MB (see the README's Supported boards table for the exact figure per platform). A platform whose own need exceeds this budget fails fast with `insufficient memory budget` and the run continues without it. If Apify itself rejects a sub-actor start because the account-wide memory limit is in use by other runs, job-feed retries with backoff before giving up on that platform.",
            "default": 0
          },
          "subactorTimeoutSecs": {
            "title": "Sub-actor timeout (seconds)",
            "minimum": 60,
            "maximum": 3600,
            "type": "integer",
            "description": "Per sub-actor timeout. A single slow platform never blocks a fast one — its results are dropped on timeout and flagged in the run summary. 600 when unset. A value above a platform's own registry timeout raises it; a lower value never shortens it."
          },
          "includeReportRowsInDataset": {
            "title": "Include report rows in dataset (advanced)",
            "type": "boolean",
            "description": "When true, also pushes the run_summary, cost_report, relevance_report, and sources_manifest items into the dataset as extra rows (this was the default before job-feed 0.9.6x). Off by default: the dataset holds only job rows, and the same report data is always available in the run's OUTPUT key-value-store record regardless of this setting.",
            "default": false
          },
          "openrouterApiKey": {
            "title": "OpenRouter API key (optional, managed mode by default)",
            "type": "string",
            "description": "OPTIONAL. When you scrape a non-ATS custom career page (e.g. `amazon.jobs/en/search`, `jobs.apple.com/en-us/search`), the orchestrator routes it to the LLM-driven website-job-extractor{,-browser}, using `deepseek/deepseek-chat-v3-0324` (no free-tier cap, strong multilingual, low hallucination). Leave this blank and website-job-extractor runs in NanoScrape's managed mode, billing its own managed PPE rate with no key needed from you. Supply your own key here and it is forwarded to the extractor instead, which then bills its standard, non-managed rate, while the LLM cost is billed to your OpenRouter account."
          },
          "geminiApiKey": {
            "title": "Gemini API key (optional cross-provider fallback)",
            "type": "string",
            "description": "OPTIONAL. If provided, wired as a cross-provider fallback behind OpenRouter — fires only if the whole OpenRouter side fails. Free tier caps at 1500 requests/day. Get one at https://ai.google.dev/."
          },
          "groqApiKey": {
            "title": "Groq API key (optional cross-provider fallback)",
            "type": "string",
            "description": "OPTIONAL. If provided, wired as a second cross-provider fallback (fires after Gemini). Groq's Llama-3.3-70b via fast inference, no per-day cap on the free tier. Get one at https://console.groq.com/keys."
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}