{
  "openapi": "3.0.1",
  "info": {
    "title": "Arbeidsplassen NAV Job Scraper — Norway Job Leads",
    "description": "Scrape Norway's national NAV job board arbeidsplassen.nav.no: title, employer, county, occupation, dates and NAV's own AI summary, plus org number, apply link, ATS vendor and named contact e-mail/phone from the ad page. 12,400+ live ads, ~550 new per day. No login.",
    "version": "0.1",
    "x-build-id": "euwCIlG9hTJ3yTUNd"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/scrapersdelight~arbeidsplassen-jobs-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-scrapersdelight-arbeidsplassen-jobs-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/scrapersdelight~arbeidsplassen-jobs-scraper/runs": {
      "post": {
        "operationId": "runs-sync-scrapersdelight-arbeidsplassen-jobs-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/scrapersdelight~arbeidsplassen-jobs-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-scrapersdelight-arbeidsplassen-jobs-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": {
          "query": {
            "title": "Search keyword",
            "type": "string",
            "description": "Free-text search across the ad (Norwegian). Examples: `sykepleier`, `utvikler`, `elektriker`, `logistikk`. Leave empty to sweep the whole live board (12,400+ ads). Sent to NAV as the `q` parameter and matched server-side.",
            "default": ""
          },
          "counties": {
            "title": "Counties (fylke)",
            "type": "array",
            "description": "Norwegian counties to keep. Several counties are OR-ed together server-side (measured: OSLO + ROGALAND = 3,274 ads). Leave empty for the whole country.",
            "items": {
              "type": "string",
              "enum": [
                "AGDER",
                "AKERSHUS",
                "BUSKERUD",
                "FINNMARK",
                "INNLANDET",
                "JAN MAYEN",
                "MØRE OG ROMSDAL",
                "NORDLAND",
                "OSLO",
                "ROGALAND",
                "SVALBARD",
                "TELEMARK",
                "TROMS",
                "TRØNDELAG",
                "VESTFOLD",
                "VESTLAND",
                "ØSTFOLD"
              ]
            },
            "default": []
          },
          "countries": {
            "title": "Countries (ads located abroad)",
            "type": "array",
            "description": "Ads placed on NAV for jobs OUTSIDE Norway have no Norwegian county, so they are only reachable through this filter. Measured live: DANMARK 5, ISLAND 6, SVERIGE 6, FINLAND 2, POLEN 2 — 24 in total. Use the Norwegian country name in capitals.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "occupationCategories": {
            "title": "Occupation categories (level 1)",
            "type": "array",
            "description": "NAV's top-level occupation taxonomy, OR-ed server-side. Live sizes: Helse og sosial 4,525 · Salg og service · Kontor og økonomi · Håndverkere · Industri og produksjon · Bygg og anlegg · IT · Transport og lager · Utdanning · Reiseliv og mat.",
            "items": {
              "type": "string",
              "enum": [
                "Helse og sosial",
                "Salg og service",
                "Utdanning",
                "Kontor og økonomi",
                "Håndverkere",
                "Reiseliv og mat",
                "Industri og produksjon",
                "Bygg og anlegg",
                "Transport og lager",
                "IT",
                "Sikkerhet og beredskap",
                "Kultur og kreative yrker",
                "Natur og miljø",
                "Uoppgitt/ ikke identifiserbare"
              ]
            },
            "default": []
          },
          "publishedWithin": {
            "title": "Published within",
            "enum": [
              "",
              "now/d",
              "now-3d",
              "now-7d"
            ],
            "type": "string",
            "description": "NAV only honours THREE relative windows server-side. For an exact date range use `Published after` / `Published before` below, which this actor applies client-side.",
            "default": ""
          },
          "sortBy": {
            "title": "Sort by",
            "enum": [
              "relevance",
              "published",
              "expires"
            ],
            "type": "string",
            "description": "Server-side ordering. `published` (newest first) is the right choice for lead work and for incremental monitoring; `relevance` only makes sense with a search keyword.",
            "default": "published"
          },
          "engagementTypes": {
            "title": "Employment type",
            "type": "array",
            "description": "Contract type, OR-ed server-side. Live sizes: Fast 8,487 · Vikariat 1,964 · Annet 769 · Engasjement 586 · Sesong 265 · Prosjekt 226 · Åremål 113 · Lærling 17.",
            "items": {
              "type": "string",
              "enum": [
                "Fast",
                "Vikariat",
                "Engasjement",
                "Prosjekt",
                "Sesong",
                "Åremål",
                "Lærling",
                "Trainee",
                "Selvstendig næringsdrivende",
                "Annet"
              ]
            },
            "default": []
          },
          "extent": {
            "title": "Full-time / part-time",
            "type": "array",
            "description": "Live sizes: Heltid 8,499 · Deltid 4,264 · Ikke oppgitt 116. Repeating the value OR-s server-side (measured Heltid+Deltid = 12,353).",
            "items": {
              "type": "string",
              "enum": [
                "Heltid",
                "Deltid",
                "Ikke oppgitt"
              ]
            },
            "default": []
          },
          "sector": {
            "title": "Sector",
            "type": "array",
            "description": "Private vs public employer. Live sizes: Privat 7,288 · Offentlig 4,749 · Ikke oppgitt 20. Public-sector ads are the ones that most often carry a named contact person with a direct phone number.",
            "items": {
              "type": "string",
              "enum": [
                "Privat",
                "Offentlig",
                "Ikke oppgitt"
              ]
            },
            "default": []
          },
          "education": {
            "title": "Education required",
            "type": "array",
            "description": "OR-ed server-side. Live sizes: Ingen krav 5,337 · Bachelor 4,523 · Fagbrev 3,138 · Master 2,232 · Fagskole 1,275 · Videregående 801 · Forskningsgrad 142.",
            "items": {
              "type": "string",
              "enum": [
                "Ingen krav",
                "Videregående",
                "Fagbrev",
                "Fagskole",
                "Bachelor",
                "Master",
                "Forskningsgrad",
                "Ikke oppgitt"
              ]
            },
            "default": []
          },
          "experience": {
            "title": "Experience required",
            "type": "array",
            "description": "OR-ed server-side. Live sizes: ingen krav til arbeidserfaring 8,379 · noe arbeidserfaring 3,312 · mye arbeidserfaring 780.",
            "items": {
              "type": "string",
              "enum": [
                "ingen krav til arbeidserfaring",
                "noe arbeidserfaring",
                "mye arbeidserfaring"
              ]
            },
            "default": []
          },
          "workLanguage": {
            "title": "Working language",
            "type": "array",
            "description": "OR-ed server-side. Live sizes: Norsk 11,597 · Engelsk 2,717 · Skandinavisk 1,478 · Samisk 113. `Engelsk` is the fastest way to a list of Norwegian employers hiring without Norwegian — the standard relocation / international-recruiter cut.",
            "items": {
              "type": "string",
              "enum": [
                "Norsk",
                "Engelsk",
                "Skandinavisk",
                "Samisk",
                "Ikke oppgitt"
              ]
            },
            "default": []
          },
          "remote": {
            "title": "Remote work",
            "type": "array",
            "description": "OR-ed server-side. Live sizes: Ikke oppgitt 7,011 · Ingen mulighet for hjemmekontor 4,478 · Delvis hjemmekontor 909 · Kun hjemmekontor 73.",
            "items": {
              "type": "string",
              "enum": [
                "Kun hjemmekontor",
                "Delvis hjemmekontor",
                "Ingen mulighet for hjemmekontor",
                "Ikke oppgitt"
              ]
            },
            "default": []
          },
          "needDriversLicense": {
            "title": "Driving licence required",
            "enum": [
              "",
              "true",
              "false",
              "Ikke oppgitt"
            ],
            "type": "string",
            "description": "Server-side. Live sizes: false 9,172 · true 3,258 · Ikke oppgitt 41.",
            "default": ""
          },
          "under18": {
            "title": "Open to under-18s",
            "enum": [
              "",
              "true",
              "false"
            ],
            "type": "string",
            "description": "NAV's own classification of whether the role is open to applicants under 18. Server-side. Live sizes: true 1,179 · false 11,292.",
            "default": ""
          },
          "hasSuperraskSoknad": {
            "title": "NAV quick-apply (superrask søknad)",
            "enum": [
              "",
              "true",
              "false"
            ],
            "type": "string",
            "description": "Ads that accept NAV's one-click application. Server-side. Live: 966 true / 819 false (the rest do not carry the flag at all).",
            "default": ""
          },
          "startUrls": {
            "title": "Search URLs from the NAV site",
            "type": "array",
            "description": "Paste `arbeidsplassen.nav.no/stillinger?...` URLs straight out of your browser — build the search in NAV's own UI, copy the address bar, drop it here. Every filter in the query string is translated, including `municipal=` and `occupationLevel2=`, which NAV's API ignores and this actor therefore applies client-side. Each URL is swept as its own search.",
            "default": [],
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "adUrls": {
            "title": "Specific ad URLs or UUIDs",
            "type": "array",
            "description": "Skip the search entirely and fetch these ads directly. Accepts full `https://arbeidsplassen.nav.no/stillinger/stilling/<uuid>` URLs or bare UUIDs. These are always fetched from the ad page, so they always carry the detail fields (org number, apply link, contact person) and are billed for both events.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "municipalities": {
            "title": "Municipalities (kommune)",
            "type": "array",
            "description": "CLIENT-SIDE filter — NAV's API silently ignores every municipality parameter (measured: `municipal`, `municipals`, `municipality`, `kommune` in every value shape leave the result count unchanged), so this actor fetches the county and filters the rows itself. Accepts `BERGEN` or NAV's own `VESTLAND.BERGEN` key. Pair it with the matching county to keep the fetch small.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "occupationSubCategories": {
            "title": "Occupation sub-categories (level 2)",
            "type": "array",
            "description": "CLIENT-SIDE filter — `occupationLevel2` is silently ignored by NAV's API. Examples: `Sykepleier` (1,068 live), `Helsefagarbeider`, `Utvikling`, `Elektriker/elektro`. Accepts `Sykepleier` or `Helse og sosial.Sykepleier`.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "cities": {
            "title": "Cities",
            "type": "array",
            "description": "Client-side filter on the ad's city (`OSLO`, `BERGEN`, `TRONDHEIM`). Case-insensitive, matches any of the ad's locations.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "postalCodes": {
            "title": "Postal codes (exact)",
            "type": "array",
            "description": "Client-side filter on the exact 4-digit Norwegian postal code of any of the ad's locations.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "postalCodePrefix": {
            "title": "Postal-code prefixes",
            "type": "array",
            "description": "Client-side. Keep ads whose postal code starts with any of these, e.g. `05` for central Oslo, `50` for Bergen.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "publishedAfter": {
            "title": "Published after (date)",
            "type": "string",
            "description": "Client-side, exact date or datetime (`2026-09-01` or an ISO timestamp). NAV only exposes three relative windows server-side, so any exact range is applied here after fetching.",
            "default": ""
          },
          "publishedBefore": {
            "title": "Published before (date)",
            "type": "string",
            "description": "Client-side, exact date or datetime.",
            "default": ""
          },
          "expiresAfter": {
            "title": "Expires after (date)",
            "type": "string",
            "description": "Client-side. Keep ads still live after this date.",
            "default": ""
          },
          "expiresBefore": {
            "title": "Expires before (date)",
            "type": "string",
            "description": "Client-side. Keep ads that expire before this date.",
            "default": ""
          },
          "applicationDueBefore": {
            "title": "Application deadline before (date)",
            "type": "string",
            "description": "Client-side urgency filter — 'every ad closing in the next 10 days'. NAV's deadline field is free text and really does carry three shapes (measured over 400 live ads: `Snarest` 91, `dd.mm.yyyy` 76, bare ISO `2026-09-13T00:00:00` 233); this actor parses both date shapes into `application_due` and flags `Snarest`/`Fortløpende` as `application_due_asap`, which passes this filter because as-soon-as-possible is more urgent than any date. Ads with an unparseable deadline are dropped.",
            "default": ""
          },
          "titleIncludeAny": {
            "title": "Title must contain any of",
            "type": "array",
            "description": "Client-side, case-insensitive substring match against the ad title and job title. Use it to tighten a broad occupation sweep.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "titleExcludeAny": {
            "title": "Title must NOT contain any of",
            "type": "array",
            "description": "Client-side, case-insensitive. Drops ads whose title or job title contains any of these.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "descriptionIncludeAny": {
            "title": "Ad text must contain any of",
            "type": "array",
            "description": "Client-side keyword match against the FULL ad body. Requires `Fetch ad details`, because the ad body only exists on the ad page.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "employerInclude": {
            "title": "Employer must match any of",
            "type": "array",
            "description": "Client-side, case-insensitive substring match on the employer / business name. Use it for named-account monitoring ('tell me every time Equinor posts').",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "employerExclude": {
            "title": "Employer must NOT match any of",
            "type": "array",
            "description": "Client-side blocklist on the employer / business name.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "excludeStaffingAgencies": {
            "title": "Exclude staffing agencies",
            "type": "boolean",
            "description": "Convenience blocklist on top of `employerExclude`: drops employers whose name matches the Norwegian staffing/recruitment vocabulary (bemanning, vikarbyrå, rekruttering, personell, manpower, adecco, randstad, jobzone, academic work, hays, workshop bemanning …). Staffing ads are re-posts of somebody else's vacancy, so they are noise for most lead use-cases and the whole point for a few.",
            "default": false
          },
          "sourceInclude": {
            "title": "Ad source must be any of",
            "type": "array",
            "description": "Client-side filter on NAV's `source` field: `FINN` (re-published from finn.no), `IMPORTAPI` (pushed by an ATS), `Stillingsregistrering` (typed straight into NAV by the employer), `AMEDIA`, `DIR`. `Stillingsregistrering` is the closest thing to a 'small employer with no recruiting stack' segment.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "sourceExclude": {
            "title": "Ad source must NOT be any of",
            "type": "array",
            "description": "Client-side. Common use: exclude `FINN` to drop everything syndicated from finn.no.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "atsVendorInclude": {
            "title": "ATS vendor must be any of",
            "type": "array",
            "description": "Client-side filter on the applicant-tracking system the employer runs, derived from the apply-link hostname (webcruiter, visma-talent, jobbnorge, teamtailor, recman, easycruit, talentech, workday, greenhouse, ansettr, finn.no …). This is the competitive-displacement list an ATS vendor buys. Requires `Fetch ad details`.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "atsVendorExclude": {
            "title": "ATS vendor must NOT be any of",
            "type": "array",
            "description": "Client-side. Requires `Fetch ad details`. Use it to strip out your own customers before handing the list to sales.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "onlyDirectPosted": {
            "title": "Only ads with no third-party ATS",
            "type": "boolean",
            "description": "Client-side. Keeps only ads whose apply link is NOT a known applicant-tracking system or job-board redirect (finn.no included) — i.e. the employer applies through their own site or a plain email. That is the 'no recruiting software yet' segment. Requires `Fetch ad details`.",
            "default": false
          },
          "isSummerJob": {
            "title": "Summer jobs only",
            "type": "boolean",
            "description": "Client-side filter on NAV's own AI summer-job classification (`aiIsSummerJob`). NAV's API exposes a summerJob facet but silently ignores `summerJob` as a query parameter, and the flag is not on the listing row — so this requires `Fetch ad details`. Live corpus: 120 summer jobs of 12,471 — under 1%, so expect the run to fetch a lot of ad pages before it finds them. You are still only billed for the ones delivered.",
            "default": false
          },
          "minPositionCount": {
            "title": "Minimum positions in the ad",
            "minimum": 0,
            "type": "integer",
            "description": "Client-side. Keep ads advertising at least this many positions — a volume-hiring signal (the live board advertises 25,014 positions across 12,471 ads). Requires `Fetch ad details`. 0 = no minimum.",
            "default": 0
          },
          "maxPositionCount": {
            "title": "Maximum positions in the ad",
            "minimum": 0,
            "type": "integer",
            "description": "Client-side. Requires `Fetch ad details`. 0 = no maximum.",
            "default": 0
          },
          "requireOrgnr": {
            "title": "Only ads with an org number",
            "type": "boolean",
            "description": "Lead-quality gate. The Norwegian organisation number is the join key to Brreg (the company register), so a row without it cannot be enriched with revenue, employees or the board. Measured fill: 75% of ads. Requires `Fetch ad details`.",
            "default": false
          },
          "requireContactEmail": {
            "title": "Only ads with a contact e-mail",
            "type": "boolean",
            "description": "Lead-quality gate on the named contact person's e-mail. Measured fill: 35% of ads — do not expect one on every row. Requires `Fetch ad details`. Personal data: see the README.",
            "default": false
          },
          "requireContactPhone": {
            "title": "Only ads with a contact phone",
            "type": "boolean",
            "description": "Lead-quality gate. Measured fill: 35% of ads. Requires `Fetch ad details`.",
            "default": false
          },
          "requireApplyLink": {
            "title": "Only ads with an apply link or e-mail",
            "type": "boolean",
            "description": "Drops ads with no way to apply. Measured fill: 90% have a URL or an e-mail. Requires `Fetch ad details`.",
            "default": false
          },
          "fetchDetails": {
            "title": "Fetch ad details (org number, apply link, contact person)",
            "type": "boolean",
            "description": "Opens each ad page as a second request and adds the fields that do NOT exist on the search API at all: organisation number, apply URL / apply e-mail, derived ATS vendor, named contact with e-mail and phone, employer homepage and description, employment type, sector, position count, start date and the full ad body. Measured fill on the ad page: employer 100%, positions 100%, ad text 100%, org number 75%, apply link 75% (90% counting e-mail), contact name 55%, contact e-mail 35%, contact phone 35%. Billed as a second event. Note that any filter which can only be decided on the ad page (ATS vendor, summer job, org number, contact e-mail…) means every candidate has to be fetched before it can be judged — you are only billed for the rows that survive, but a rare filter will spend real run time.",
            "default": false
          },
          "maxItems": {
            "title": "Max ads",
            "minimum": 0,
            "type": "integer",
            "description": "Hard cap on the rows delivered and billed, across every search and slice. 0 = no cap (a full sweep of the live board is ~12,400 ads).",
            "default": 100
          },
          "autoSliceCorpus": {
            "title": "Auto-slice past NAV's 10,000-result window",
            "type": "boolean",
            "description": "NAV's Elasticsearch refuses `from + size > 10000` (measured: `from=9900` is fine, `from=9901` returns HTTP 400 'Pagination depth exceeds maximum allowed window'). The live board is ~12,470 ads, so a full sweep is impossible in one query. With this on, the actor slices the search by county (largest slice OSLO = 2,185) and then by occupation if a slice is still too deep, sweeps abroad-located ads through the country facet, and deduplicates on ad UUID. Turn it off and the run stops at 10,000.",
            "default": true
          },
          "includeAdTextPlain": {
            "title": "Include the ad body as plain text",
            "type": "boolean",
            "description": "Adds `ad_text` — NAV's ad body with the HTML stripped. Only present when `Fetch ad details` is on.",
            "default": true
          },
          "includeAdTextHtml": {
            "title": "Include the ad body as HTML",
            "type": "boolean",
            "description": "Adds `ad_text_html`, the raw markup. Off by default because it can be 15 KB per row.",
            "default": false
          },
          "includeAiTags": {
            "title": "Include NAV's AI enrichment",
            "type": "boolean",
            "description": "NAV runs its own model over every ad and publishes the result for free: a one-paragraph `short_summary` (100% fill), skill tags (`ai_tags`, 99.8% fill) and an under-18 assessment. Keeping this on is the cheapest value density in the row.",
            "default": true
          },
          "includeEmbeddingVector": {
            "title": "Include NAV's ad embedding vector",
            "type": "boolean",
            "description": "Adds `embedding_vector`, the 256-float `compositeAdVector` NAV publishes on the ad page for semantic matching. Off by default: it multiplies the size of every row. Requires `Fetch ad details`.",
            "default": false
          },
          "includeRawSource": {
            "title": "Include the untouched NAV objects",
            "type": "boolean",
            "description": "Attaches `raw_source` (the search API's `_source`) and, when details are fetched, `raw_detail` (NAV's own `adData` object). For pipelines that would rather map the fields themselves.",
            "default": false
          },
          "flattenOutput": {
            "title": "Flat lead rows",
            "type": "boolean",
            "description": "On (default): one flat row per ad, list fields joined with `; ` — the shape a CRM or a spreadsheet wants. Off: locations, occupations, categories, contacts, education, experience and languages come back as arrays and objects.",
            "default": true
          },
          "deduplicate": {
            "title": "Deduplicate by ad UUID",
            "type": "boolean",
            "description": "On (default): each ad is delivered and billed at most once, even though NAV's county facet counts multi-county ads twice (county slices sum to 13,008 against a 12,460 corpus). Turn it off only if you want each of several search URLs to return its own copy; ads are never duplicated inside one search either way.",
            "default": true
          },
          "onlyNewSince": {
            "title": "Only ads published after",
            "type": "string",
            "description": "ISO date or datetime. Drops anything published earlier — the simple form of monitoring. For a running watch that remembers what it has already seen, use `State key` instead.",
            "default": ""
          },
          "stateKey": {
            "title": "State key (incremental monitoring)",
            "type": "string",
            "description": "Give this run a name (e.g. `oslo-nurses`) and the actor stores every ad UUID it has delivered under that name in a NAMED key-value store. On the next run with the same key, ads already seen are dropped BEFORE delivery, so you only ever pay for genuinely new vacancies. Leave empty for a one-off scrape.",
            "default": ""
          },
          "maxConcurrency": {
            "title": "Concurrent detail requests",
            "minimum": 1,
            "maximum": 30,
            "type": "integer",
            "description": "How many ad pages to fetch in parallel when `Fetch ad details` is on. 8 is a courteous default against NAV; raise it only if you are sweeping tens of thousands of ads.",
            "default": 8
          },
          "maxRequestRetries": {
            "title": "Retries per request",
            "minimum": 0,
            "maximum": 10,
            "type": "integer",
            "description": "Keep this at 3 or more. NAV itself is stable (measured 20/20 on ad pages and 56/57 on searches), but the Apify proxy tunnel returns a transient `595` on roughly 2-3% of calls; the retry converts that to ~100%.",
            "default": 3
          },
          "requestTimeoutSecs": {
            "title": "Request timeout (seconds)",
            "minimum": 5,
            "maximum": 300,
            "type": "integer",
            "description": "Per-request timeout. NAV answers a 100-row search in ~1.2 s through a datacenter proxy.",
            "default": 45
          },
          "requestDelayMs": {
            "title": "Delay between search pages (ms)",
            "minimum": 0,
            "maximum": 10000,
            "type": "integer",
            "description": "Politeness pause between paged search requests.",
            "default": 200
          },
          "proxyConfiguration": {
            "title": "Proxy",
            "type": "object",
            "description": "Apify DATACENTER proxies are enough — measured through the full escalation ladder: direct 200, datacenter 200, residential NO 200, residential US 200. NAV is not geo-blocked, so no country pin is needed. A fresh proxy session is minted on every retry.",
            "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}