{
  "openapi": "3.0.1",
  "info": {
    "title": "Poland Pharmacy Register Scraper - Licensed Pharmacies + NIP",
    "description": "From $2.50 per 1,000 rows. Scrape Poland's official pharmacy register (Rejestr Aptek): all 23,993 licensed pharmacies with owner company, NIP, REGON, KRS, permit number and date, phone and e-mail. Canonical voivodeship, powiat, gmina, TERYT and opening hours joined from the state's own bulk export.",
    "version": "0.1",
    "x-build-id": "SzxDAjFodD6UypEOO"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/scrapersdelight~rejestr-aptek-pl-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-scrapersdelight-rejestr-aptek-pl-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~rejestr-aptek-pl-scraper/runs": {
      "post": {
        "operationId": "runs-sync-scrapersdelight-rejestr-aptek-pl-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~rejestr-aptek-pl-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-scrapersdelight-rejestr-aptek-pl-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": {
          "voivodeships": {
            "title": "Voivodeships (regions)",
            "type": "array",
            "description": "Leave empty for all 16 (the whole country). Corpus sizes on 2026-09-07: mazowieckie 3,060 · śląskie 2,843 · łódzkie 2,268 · wielkopolskie 2,173 · małopolskie 2,171 · dolnośląskie 1,763 · lubelskie 1,390 · podkarpackie 1,369 · pomorskie 1,306 · kujawsko-pomorskie 1,176 · zachodniopomorskie 1,004 · świętokrzyskie 789 · warmińsko-mazurskie 769 · podlaskie 719 · opolskie 615 · lubuskie 578. Picking any region forces the per-voivodeship crawl (see \"How to slice the crawl\"), and the region check fails closed: a row whose region this run could not establish is dropped, never delivered unverified.",
            "items": {
              "type": "string",
              "enum": [
                "dolnośląskie",
                "kujawsko-pomorskie",
                "lubelskie",
                "lubuskie",
                "łódzkie",
                "małopolskie",
                "mazowieckie",
                "opolskie",
                "podkarpackie",
                "podlaskie",
                "pomorskie",
                "śląskie",
                "świętokrzyskie",
                "warmińsko-mazurskie",
                "wielkopolskie",
                "zachodniopomorskie"
              ],
              "enumTitles": [
                "Dolnośląskie (Lower Silesia) — 1,763",
                "Kujawsko-pomorskie — 1,176",
                "Lubelskie — 1,390",
                "Lubuskie — 578",
                "Łódzkie — 2,268",
                "Małopolskie (Lesser Poland) — 2,171",
                "Mazowieckie (Masovia) — 3,060",
                "Opolskie — 615",
                "Podkarpackie — 1,369",
                "Podlaskie — 719",
                "Pomorskie (Pomerania) — 1,306",
                "Śląskie (Silesia) — 2,843",
                "Świętokrzyskie — 789",
                "Warmińsko-mazurskie — 769",
                "Wielkopolskie (Greater Poland) — 2,173",
                "Zachodniopomorskie (West Pomerania) — 1,004"
              ]
            }
          },
          "activeOnly": {
            "title": "Active pharmacies only",
            "type": "boolean",
            "description": "THE DEAD-ROW TRAP. 43% of the register — 10,260 of 23,993 rows on 2026-09-07 — is closed, suspended or temporarily shut. A naive scrape of page 0 sees 84% active and reports 98.9% e-mail fill; the true corpus is 57.2% active with 83.5% e-mail fill. Leave this on unless you want the dead rows. The register CANNOT filter on status, so this runs client-side: dead rows are dropped before delivery and are never charged.",
            "default": true
          },
          "statuses": {
            "title": "Statuses (overrides \"Active only\")",
            "type": "array",
            "description": "Pick exact statuses. Corpus counts 2026-09-07. \"Oczekująca\" is the highest-value trigger row there is: a permit has been granted and the pharmacy has not opened yet — but there are only 20 of them in the whole register, so do not build a business on that alone.",
            "items": {
              "type": "string",
              "enum": [
                "AKTYWNA",
                "NIEAKTYWNA",
                "OCZEKUJĄCA",
                "NIEAKTYWNA-ZAWIESZENIE_DZIAŁALNOŚCI",
                "CZASOWO_NIECZYNNA"
              ],
              "enumTitles": [
                "Active (aktywna) — 13,733",
                "Closed (nieaktywna) — 9,950",
                "Pending, permit granted (oczekująca) — 20",
                "Suspended (nieaktywna – zawieszenie działalności) — 166",
                "Temporarily closed (czasowo nieczynna) — 124"
              ]
            }
          },
          "pharmacyTypes": {
            "title": "Pharmacy types",
            "type": "array",
            "description": "Leave empty for all ten. Community pharmacies and pharmacy points are the retail lead; hospital pharmacy departments belong to a hospital, not to a retail buyer, and are ~16% of the register. Filtered client-side (the register cannot filter on type).",
            "items": {
              "type": "string",
              "enum": [
                "APTEKA_OGOLNODOSTEPNA",
                "PUNKT_APTECZNY",
                "DZIAL_FARMACJI_SZPITALNEJ",
                "APTEKA_SZPITALNA",
                "APTEKA_SZPITALNA_BEZ_ZGODY",
                "APTEKA_ZAKLADOWA",
                "APTEKA_ZAKLADOWA_BEZ_ZGODY",
                "APTEKA_ZAKLADOWA_MON",
                "APTEKA_ZAKLADOWA_MON_BEZ_ZGODY",
                "DZIAL_FARMACJI_SZPITALNEJ_MON"
              ],
              "enumTitles": [
                "Community pharmacy (apteka ogólnodostępna) — 18,961",
                "Pharmacy point (punkt apteczny) — 2,729",
                "Hospital pharmacy department — 1,586",
                "Hospital pharmacy — 333",
                "Hospital pharmacy, no consent on file — 343",
                "Institutional pharmacy — 17",
                "Institutional pharmacy, no consent — 6",
                "Institutional pharmacy (Ministry of Defence) — 8",
                "Institutional pharmacy MoD, no consent — 4",
                "Hospital pharmacy department (MoD) — 6"
              ]
            }
          },
          "city": {
            "title": "City contains",
            "type": "string",
            "description": "Server-side substring match on the pharmacy's town. ⚠️ Case-insensitive but DIACRITIC-SENSITIVE: \"Kraków\" and \"krak\" both return 531 pharmacies, \"krakow\" returns 0. Type the Polish spelling."
          },
          "district": {
            "title": "District (powiat) contains",
            "type": "string",
            "description": "Server-side substring match on the powiat, e.g. \"prudnicki\" → 32 pharmacies."
          },
          "commune": {
            "title": "Commune (gmina) contains",
            "type": "string",
            "description": "Server-side substring match on the gmina, e.g. \"Prudnik\" → 14 pharmacies."
          },
          "street": {
            "title": "Street contains",
            "type": "string",
            "description": "Server-side substring match on the street name, e.g. \"Szpitalna\" → 171 pharmacies."
          },
          "postcodeStartsWith": {
            "title": "Postcode starts with",
            "type": "string",
            "description": "Client-side prefix match on the pharmacy postcode (the register has no server-side postcode filter — sending one is silently ignored and returns the whole corpus, so this Actor never sends it). Polish postcodes are NN-NNN, e.g. \"00-\" for central Warsaw."
          },
          "pharmacyNameContains": {
            "title": "Pharmacy name contains",
            "type": "string",
            "description": "Server-side substring match on the trading name, e.g. \"apteka\" → 8,264. Note 16.2% of the register has no trading name at all (mostly hospital pharmacy departments), so this filter silently excludes them."
          },
          "registerIds": {
            "title": "Look up specific register IDs",
            "type": "array",
            "description": "One or more register IDs (the `register_id` / `originId` field, and the same id the official bulk export uses). Each is fetched with an exact server-side lookup — one small request per id, no crawl. When this is set, every other search filter still applies but the voivodeship fan-out is skipped.",
            "items": {
              "type": "string"
            }
          },
          "ownerNameContains": {
            "title": "Owner name contains",
            "type": "string",
            "description": "Server-side substring match on the owner entity's name, e.g. \"pharma\" → 747."
          },
          "ownerType": {
            "title": "Independent or chain?",
            "enum": [
              "any",
              "independent",
              "chain"
            ],
            "type": "string",
            "description": "Client-side split on the owner's legal form (falling back to KRS presence when the form is missing). \"Independent\" = sole trader, civil-law partnership or other non-registered person — 9,423 owners of 23,993. \"Chain / company\" = everything with a company legal form.",
            "default": "any"
          },
          "ownerLegalForms": {
            "title": "Owner legal forms",
            "type": "array",
            "description": "Exact server-side filter (the register does honour this one — verified: 18 → 8,427 rows, 20 → 966, 1 → 6,904). Ticking several runs one request per value and merges the results, deduplicated by register id.",
            "items": {
              "type": "string",
              "enum": [
                "18",
                "1",
                "19",
                "20",
                "7",
                "5",
                "2",
                "3",
                "9",
                "12",
                "13",
                "11",
                "8",
                "16",
                "6",
                "15",
                "4",
                "10",
                "17",
                "14"
              ],
              "enumTitles": [
                "Sole trader (osoba fizyczna prowadząca DG) — 8,427",
                "Limited liability company (sp. z o.o.) — 6,904",
                "General partnership (spółka jawna) — 4,553",
                "Civil-law partnership (spółka cywilna) — 966",
                "Public healthcare entity (SPZOZ) — 671",
                "Joint-stock company (S.A.) — 668",
                "Limited partnership (sp.k.) — 336",
                "sp. z o.o. sp.k. — 209",
                "Foundation / association — 159",
                "Church or religious body — 76",
                "sp. z o.o. with local-government stake — 61",
                "Public budget unit — 44",
                "Professional partnership (sp.p.) — 33",
                "Other institution or person — 30",
                "Limited joint-stock partnership (S.K.A.) — 27",
                "Research institute — 12",
                "sp. z o.o. S.K.A. — 5",
                "Cooperative — 5",
                "Other domestic/foreign legal person — 3",
                "S.A. with local-government or state stake — 1"
              ]
            }
          },
          "ownerNip": {
            "title": "Owner NIP (exact)",
            "type": "string",
            "description": "Return only pharmacies owned by this Polish tax number — the portfolio view of one chain. Digits are compared, so dashes and spaces are fine. The register has NO server-side NIP filter (sending one is ignored and returns all 23,993), so this is matched client-side over the crawled set: expect a full-register read unless you narrow it with a voivodeship or a legal form as well."
          },
          "requireOwnerNip": {
            "title": "Only rows that carry an owner NIP",
            "type": "boolean",
            "description": "Drops the 7.0% of the corpus with no owner tax number (0.2% of active rows). Filtered client-side; dropped rows are never charged.",
            "default": false
          },
          "ownerFirstName": {
            "title": "Owner first name contains",
            "type": "string",
            "description": "Server-side substring match, e.g. \"Jan\" → 120. ⚠️ Personal data: this searches named private individuals (sole traders, 35.8% of the register)."
          },
          "ownerLastName": {
            "title": "Owner surname contains",
            "type": "string",
            "description": "Server-side substring match, e.g. \"Kowalski\" → 6. ⚠️ Personal data — see above."
          },
          "permitIssuedInLastDays": {
            "title": "Permit issued in the last N days",
            "minimum": 1,
            "type": "integer",
            "description": "Server-side lower bound on the permit issue date. Verified live: the register honours it exactly (issueDateFrom=2026-06-01 returned rows whose earliest issue date was exactly 2026-06-01, with no nulls). Leave empty for no window."
          },
          "permitIssuedFrom": {
            "title": "Permit issued from (YYYY-MM-DD)",
            "type": "string",
            "description": "Server-side lower bound. If you also set \"in the last N days\", the tighter of the two wins."
          },
          "permitIssuedTo": {
            "title": "Permit issued to (YYYY-MM-DD)",
            "type": "string",
            "description": "Server-side upper bound. Combined with the lower bound this is a true server-side date range — measured: 2026-01-01 → 138 rows, ≤ 1991-01-01 → 622, the combined 2026-01-01…2026-06-30 window → 108."
          },
          "permitNumberContains": {
            "title": "Permit number contains",
            "type": "string",
            "description": "Server-side substring match on the licence number, e.g. \"WIF\" → 9,218."
          },
          "permitTypes": {
            "title": "Permit types",
            "type": "array",
            "description": "Client-side. Corpus counts 2026-09-07: Zezwolenie (licence) 17,879 · Koncesja (the pre-2001 concession) 4,256 · Zgoda (consent, used for hospital and institutional pharmacies) 1,549.",
            "items": {
              "type": "string",
              "enum": [
                "ZEZWOLENIE",
                "KONCESJA",
                "ZGODA"
              ],
              "enumTitles": [
                "Zezwolenie (licence) — 17,879",
                "Koncesja (concession) — 4,256",
                "Zgoda (consent) — 1,549"
              ]
            }
          },
          "permitIssuerContains": {
            "title": "Permit issuer contains",
            "type": "string",
            "description": "Client-side substring match on the issuing authority — one of 71 values, mostly the 16 provincial pharmaceutical inspectorates (Wojewódzki Inspektor Farmaceutyczny). e.g. \"Katowicach\" for the Silesian inspectorate."
          },
          "changedInLastDays": {
            "title": "Record changed in the last N days",
            "minimum": 1,
            "type": "integer",
            "description": "Only return records the register edited within this window."
          },
          "changedFrom": {
            "title": "Changed from (YYYY-MM-DD)",
            "type": "string",
            "description": "Lower bound on the register's own last-edited date."
          },
          "changedTo": {
            "title": "Changed to (YYYY-MM-DD)",
            "type": "string",
            "description": "Upper bound on the register's own last-edited date."
          },
          "dedupeAcrossRuns": {
            "title": "Skip pharmacies already delivered by an earlier run",
            "type": "boolean",
            "description": "Remembers every register id delivered, in a NAMED key-value store ('rejestr-aptek-seen-ids') so the memory survives scheduled runs — an unnamed store is wiped every run, which would make every pharmacy look new every time. Skipped rows are never charged.",
            "default": false
          },
          "requireEmailOrPhone": {
            "title": "Must have an e-mail or a phone",
            "type": "boolean",
            "description": "Drops rows with neither. On active rows this removes 0.6%.",
            "default": false
          },
          "requireEmail": {
            "title": "Must have an e-mail",
            "type": "boolean",
            "description": "Drops rows with no e-mail address (1.6% of active rows, 16.5% of the whole register).",
            "default": false
          },
          "requirePhone": {
            "title": "Must have a phone number",
            "type": "boolean",
            "description": "Drops rows with no phone number (2.2% of active rows, 10.5% of the whole register).",
            "default": false
          },
          "onlineSalesOnly": {
            "title": "Sells online (mail-order) only",
            "type": "boolean",
            "description": "Only pharmacies flagged as selling by mail order — 354 in the whole register, 247 of them active. A small, specific segment: these are the ones with an e-commerce operation to sell software or fulfilment to.",
            "default": false
          },
          "includeOfficialExportFields": {
            "title": "Add official-export fields (powiat, gmina, TERYT, opening hours, launch date)",
            "type": "boolean",
            "description": "One extra download per run. MEASURED ON THE APIFY PLATFORM 2026-09-08 with the 17.5 MB CSV: 5 seconds fetched direct out of the container (whole 200-row run: 9.4 s), against 42.7 s through the Apify proxy — and on one run the proxied attempt timed out at 180 s and the retry pushed the whole run to 249 s. So the export is fetched DIRECT by default; the paged search still uses the proxy. The download is also deadline-aware: if too little of the run's time budget is left it is skipped, the log says so, and it is not charged. Charged once per run as \"Official bulk-export join\", and only if the download succeeded AND at least one delivered row actually gained a field from it.",
            "default": true
          },
          "officialExportSource": {
            "title": "Which export file",
            "enum": [
              "csv",
              "xml"
            ],
            "type": "string",
            "description": "CSV (17.5 MB, 3.6 s direct / 22.6 s proxied) is the default and carries the most columns, including the activity scope and the deputy manager. XML (54.1 MB, 82 s direct / 152.7 s proxied) is 3.1× bigger and 6.8× slower for a smaller field set — pick it ONLY if you need latitude/longitude, which is its one exclusive column and is filled on 21.9% of the register (34.5% of active rows). Those coordinates are delivered as real WGS84 degrees: the state publishes them as PUWG-1992 grid metres under attributes named \"latitude\"/\"longitude\" that are also swapped against their own names, so this Actor does the inverse projection itself and keeps the raw grid pair in puwg92_x / puwg92_y so you can check it.",
            "default": "csv"
          },
          "officialExportViaProxy": {
            "title": "Fetch the bulk export through the proxy",
            "type": "boolean",
            "description": "Off by default, and you almost certainly want it off. The export is a static government file with no anti-bot, so the proxy adds nothing — and it measured 4-25x slower on the platform (5 s direct vs 42.7 s proxied, with one proxied attempt timing out at 180 s). Turn it on only if your account requires all outbound traffic to go through the Apify proxy.",
            "default": false
          },
          "includeManagerNames": {
            "title": "Include the pharmacy manager (personal data)",
            "type": "boolean",
            "description": "⚠️ OFF by default on purpose. The manager and deputy manager are named pharmacists, and the licence number (numer prawa wykonywania zawodu) is their personal professional-practice number. The register publishes them and they are filled on 99.9% of active rows, but they are personal data under GDPR and you need your own lawful basis to process them. Requires the export join. (The owners' PESEL national identity number is hard-dropped in code under every setting and can never be emitted — it was null on all 23,993 rows and the state's own XSD excludes it from the public data scope.)",
            "default": false
          },
          "includeAllOwners": {
            "title": "Include every owner as an array",
            "type": "boolean",
            "description": "Adds an `owners[]` array. Only 3 rows in the whole register list more than one owner in the search endpoint, so the flat owner_* columns cover 99.99% of cases — this is for completeness, not for volume.",
            "default": false
          },
          "includePermitHistory": {
            "title": "Include the full permit-amendment history",
            "type": "boolean",
            "description": "Adds a `permit_history[]` array of every recorded amendment (issue date, document number, description of the change). Present on 44.8% of the corpus and 52.3% of active rows. The most recent amendment is always emitted as three flat columns whether or not this is on.",
            "default": false
          },
          "includeRawJson": {
            "title": "Include the raw register record",
            "type": "boolean",
            "description": "Adds `raw_json`, the untouched search response for the row, minus the PESEL field which is always stripped. Roughly triples the dataset size — use it to check a mapping, not for bulk exports.",
            "default": false
          },
          "maxItems": {
            "title": "Max pharmacies",
            "minimum": 0,
            "type": "integer",
            "description": "0 = every matching row. The whole register is 23,993 rows; active-only is 13,733. Note the register cannot filter by status, so an active-only run still reads the full result set server-side and drops the dead rows before delivery — you are not charged for them.",
            "default": 200
          },
          "crawlStrategy": {
            "title": "How to slice the crawl",
            "enum": [
              "auto",
              "single-stream",
              "by-voivodeship"
            ],
            "type": "string",
            "description": "\"Auto\" is right almost always. It crawls ONE national stream in the order you asked for when your run is capped — so \"the newest 200 pharmacies in Poland\" really is national, not the newest 200 in whichever region happened to be crawled first — and switches to one stream per voivodeship when the run is unbounded, larger than 5,000 rows, or when you picked regions or owner legal forms. Per-voivodeship streams run in parallel and are the only way to apply a region AT ALL: pharmacyProvince is a per-request server filter and the search endpoint returns address.province null on 100% of its rows. So if you pick voivodeships and set this to \"single-stream\", the Actor overrides you back to \"by-voivodeship\" and logs why — a national crawl would deliver and bill rows from every other region.",
            "default": "auto"
          },
          "sortBy": {
            "title": "Sort by",
            "enum": [
              "originId",
              "permission.issueDate",
              "dateOfChanged",
              "permission.permissionNumber",
              "name"
            ],
            "type": "string",
            "description": "PAGING INTEGRITY MATTERS HERE. Offset paging over a mutable sort key loses rows: measured on małopolskie (2,171 declared), a contiguous `dateOfChanged` crawl returned 2,171 rows but only 2,165 unique — and the 6 duplicates were 6 rows it never returned at all. The same crawl sorted by register ID returned 2,171/2,171. Register ID is unique, immutable and monotonic; three separate full-corpus crawls (ID ascending, ID descending at page size 1,000 and at 500) each returned 23,993 unique ids and agreed on exactly the same set. The other sorts are offered because they are useful, and the run reports precisely what they covered.",
            "default": "originId"
          },
          "sortDirection": {
            "title": "Sort direction",
            "enum": [
              "DESC",
              "ASC"
            ],
            "type": "string",
            "description": "Descending on register ID puts the newest register entries first, which are 93.8% active in the first 500 rows against 47.4% at the oldest end — so a capped active-only run fills up roughly twice as fast.",
            "default": "DESC"
          },
          "pageSize": {
            "title": "Rows per request",
            "minimum": 20,
            "maximum": 5000,
            "type": "integer",
            "description": "The register accepts up to 5,000 (and answered a 10,000-row request in 37.7 s). 500 is a good balance: measured through a pinned Apify datacenter proxy session, 20 back-to-back requests ran 20/20 with a 2.9 s median. The Actor lowers this automatically when your row cap is small, so a 50-row run never pulls a 1,000-row page.",
            "default": 500
          },
          "startPage": {
            "title": "Start at page (0-based)",
            "minimum": 0,
            "type": "integer",
            "description": "Skip the first N pages of every stream — for resuming a large export. Any run with a non-zero start page is reported as INCOMPLETE, because it is.",
            "default": 0
          },
          "maxPagesPerStream": {
            "title": "Max pages per stream",
            "minimum": 0,
            "type": "integer",
            "description": "0 = no limit. A hard ceiling on requests per voivodeship, for cost control on exploratory runs. Streams cut short by it are reported as INCOMPLETE.",
            "default": 0
          },
          "proxyConfiguration": {
            "title": "Proxy",
            "type": "object",
            "description": "OFF by default, and that is deliberate. MEASURED ON THE APIFY PLATFORM 2026-09-08 on the identical crawl (mazowieckie, 3,060 rows read, 618 delivered): 22.4 s direct out of the container, 58.4 s through the Apify proxy at page size 200, and 336.9 s through the Apify proxy at page size 500 — roughly 47 s for every 1.8 MB page. The register has no anti-bot of any kind and no rate limiting was seen across 100+ measured requests, so the proxy buys nothing here and costs up to 15x. Turn it on if your own egress is blocked or your account requires it; the Actor then pins one proxy session per crawl stream, which measured 20/20 successful with a 5.6 s p90 against 39/40 and a 47.3 s p90 unpinned.",
            "default": {
              "useApifyProxy": false
            }
          },
          "maxConcurrency": {
            "title": "Parallel voivodeship streams",
            "minimum": 1,
            "maximum": 8,
            "type": "integer",
            "description": "How many voivodeship partitions to crawl at once. Each gets its own pinned proxy session. 4 is polite to a government server and still cuts a full-register crawl to roughly a quarter of the serial time.",
            "default": 4
          },
          "requestTimeoutSecs": {
            "title": "Request timeout (seconds)",
            "minimum": 15,
            "maximum": 300,
            "type": "integer",
            "description": "Per request. The bulk-export download gets its own, longer budget.",
            "default": 90
          },
          "maxRetries": {
            "title": "Retries per request",
            "minimum": 0,
            "maximum": 8,
            "type": "integer",
            "description": "Exponential backoff with jitter. The one failure seen in 60 measured proxied requests was a socket hang-up with no HTTP status and no rate-limit signature — transport, not throttling, and exactly what a retry fixes. An HTTP 500 is never retried: for this register 500 means the query itself is malformed, and the run fails loudly instead of hammering.",
            "default": 4
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}