{
  "openapi": "3.0.1",
  "info": {
    "title": "Polish Real Estate Aggregator",
    "description": "Unified real-estate search across Poland's 5 largest portals (Otodom, Morizon, Gratka, OLX, Nieruchomości-online). Runs all in parallel and groups duplicate listings - when the same property is advertised on multiple portals, you get one canonical row plus a list of all sources.",
    "version": "1.3",
    "x-build-id": "uquvKgIrUghapBlbH"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/trev0n~polish-real-estate-aggregator/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-trev0n-polish-real-estate-aggregator",
        "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/trev0n~polish-real-estate-aggregator/runs": {
      "post": {
        "operationId": "runs-sync-trev0n-polish-real-estate-aggregator",
        "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/trev0n~polish-real-estate-aggregator/run-sync": {
      "post": {
        "operationId": "run-sync-trev0n-polish-real-estate-aggregator",
        "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": {
          "city": {
            "title": "City",
            "type": "string",
            "description": "City to search (e.g., 'Kraków', 'Warszawa', 'Wrocław'). Used for all portals."
          },
          "propertyType": {
            "title": "Property Type",
            "enum": [
              "mieszkanie",
              "dom",
              "dzialka",
              "lokal"
            ],
            "type": "string",
            "description": "Type of property.",
            "default": "mieszkanie"
          },
          "searchType": {
            "title": "Search Type",
            "enum": [
              "sprzedaz",
              "wynajem"
            ],
            "type": "string",
            "description": "Sale or rent.",
            "default": "sprzedaz"
          },
          "priceMin": {
            "title": "Price Min (PLN)",
            "minimum": 0,
            "type": "integer",
            "description": "Minimum price in PLN."
          },
          "priceMax": {
            "title": "Price Max (PLN)",
            "minimum": 0,
            "type": "integer",
            "description": "Maximum price in PLN."
          },
          "areaMin": {
            "title": "Area Min (m²)",
            "minimum": 0,
            "type": "integer",
            "description": "Minimum area in square meters."
          },
          "areaMax": {
            "title": "Area Max (m²)",
            "minimum": 0,
            "type": "integer",
            "description": "Maximum area in square meters."
          },
          "roomsMin": {
            "title": "Rooms Min",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "Minimum number of rooms."
          },
          "roomsMax": {
            "title": "Rooms Max",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "Maximum number of rooms."
          },
          "sellerType": {
            "title": "Seller type",
            "enum": [
              "all",
              "private",
              "business"
            ],
            "type": "string",
            "description": "Filter offers by who is selling. 'Private owners only' keeps offers posted directly by owners and drops anything from real-estate agencies or developers — useful when you want to avoid intermediaries. 'Agencies & developers only' does the opposite. Note: this is independent of the primary/secondary market — agencies and developers also advertise on the secondary market, so filtering by market alone will not exclude them.",
            "default": "all"
          },
          "maxItemsPerPortal": {
            "title": "Max Items Per Portal",
            "minimum": 1,
            "type": "integer",
            "description": "Limit applied to each scraper separately. Final dataset can be up to N × (number of portals) before dedup.",
            "default": 50
          },
          "portals": {
            "title": "Portals to scrape",
            "uniqueItems": true,
            "type": "array",
            "description": "Select which portals to query. Defaults to all 7.",
            "items": {
              "type": "string",
              "enum": [
                "otodom",
                "morizon",
                "gratka",
                "olx",
                "nol",
                "adresowo",
                "domiporta"
              ],
              "enumTitles": [
                "Otodom",
                "Morizon",
                "Gratka",
                "OLX",
                "Nieruchomości-online",
                "Adresowo",
                "Domiporta"
              ]
            },
            "default": [
              "otodom",
              "morizon",
              "gratka",
              "olx",
              "nol",
              "adresowo",
              "domiporta"
            ]
          },
          "scoreThreshold": {
            "title": "Match Confidence Threshold",
            "minimum": 50,
            "maximum": 100,
            "type": "integer",
            "description": "Confidence cutoff (0-100) for merging two listings into the same cluster. Higher values are stricter (fewer merges, near-zero false positives); lower values catch more cross-portal matches at the cost of occasional false merges. 85 is the recommended default.",
            "default": 85
          },
          "skipPhash": {
            "title": "Fast Mode",
            "type": "boolean",
            "description": "Run with reduced matching accuracy for faster execution. Recommended only for very large queries — leave off for best deduplication quality.",
            "default": false
          },
          "emitAllListings": {
            "title": "Emit all per-portal listings",
            "type": "boolean",
            "description": "By default the dataset contains one row per unique property (the canonical listing), with all cross-portal variants collapsed into the `sources` field. Enable this to also emit the per-portal duplicate listings (marked isCanonical=false) — useful for comparing prices or wording across portals, but creates multiple rows per property.",
            "default": false
          },
          "phashCacheName": {
            "title": "Match cache store name",
            "type": "string",
            "description": "Name of the named Apify key-value store used to cache matching data across runs. Any two runs using the same store share the cache — repeated runs on overlapping listings reuse previously computed match data and run faster. Leave default unless you want to isolate caches per search profile.",
            "default": "aggregator-phash-cache"
          },
          "dateFrom": {
            "title": "Posted from (date)",
            "type": "string",
            "description": "Only keep listings published on or after this date (inclusive), format YYYY-MM-DD. Leave empty for no lower bound. Note: Adresowo and Nieruchomości-online do not publish a listing date at all — see 'Listings without a date' below."
          },
          "dateTo": {
            "title": "Posted to (date)",
            "type": "string",
            "description": "Only keep listings published on or before this date (inclusive), format YYYY-MM-DD. Leave empty for 'up to today'."
          },
          "dateBasis": {
            "title": "Date to filter on",
            "enum": [
              "created",
              "modified"
            ],
            "type": "string",
            "description": "Which date the range applies to. 'Published' uses the original posting date. 'Last updated' uses the date the offer was last refreshed by the seller (falls back to the publication date when a portal does not report an update date) — useful for catching re-listed or price-changed offers.",
            "default": "created"
          },
          "undatedListings": {
            "title": "Listings without a date",
            "enum": [
              "keep",
              "drop"
            ],
            "type": "string",
            "description": "What to do with offers whose portal does not report any date (all Adresowo and Nieruchomości-online offers, plus occasional records elsewhere). 'Keep' passes them through — a missing date is not the same as a date outside the range. 'Drop' gives a strict range containing only offers with a confirmed date.",
            "default": "keep"
          },
          "excludeListings": {
            "title": "Exclude listings (URLs or IDs)",
            "type": "array",
            "description": "Listings you have already picked, contacted or rejected — one per line. Paste the listing URL from any of the seven portals or the `offerId` / `url` value from a previous dataset. Tracking parameters (utm_*, fbclid) and trailing slashes are ignored. The whole property is skipped, not just that one link: if you exclude an Otodom listing, the same flat found on Morizon or Gratka disappears as well.",
            "items": {
              "type": "string"
            }
          },
          "skipSeenListings": {
            "title": "Skip listings from previous runs",
            "type": "boolean",
            "description": "Remember every listing this actor has returned and drop it (together with its cross-portal copies) from all future runs, so a scheduled run delivers only properties you have not seen yet. The memory lives in the named key-value store below and is shared by all runs that use the same store name. A run where everything is already known emits a single informational row instead of an empty dataset.",
            "default": false
          },
          "seenStoreName": {
            "title": "Memory store name",
            "type": "string",
            "description": "Name of the Apify key-value store that keeps the list of already-returned listings (used only when 'Skip listings from previous runs' is on). Use a different name per search profile (e.g. `seen-krakow-3-rooms`) to keep their memories separate. Delete the store in Apify Console → Storage to start over.",
            "default": "aggregator-seen-listings"
          },
          "otodomProxy": {
            "title": "Otodom proxy",
            "type": "object",
            "description": "Proxy used when scraping Otodom. Defaults to Apify Residential PL — Otodom's anti-bot (DataDome) blocks datacenter IPs, so this is required for it to work. Override only if you know what you're doing.",
            "default": {
              "useApifyProxy": true,
              "apifyProxyGroups": [
                "RESIDENTIAL"
              ],
              "apifyProxyCountry": "PL"
            }
          },
          "morizonProxy": {
            "title": "Morizon proxy",
            "type": "object",
            "description": "Proxy used when scraping Morizon. Default: no proxy (Morizon doesn't require it)."
          },
          "gratkaProxy": {
            "title": "Gratka proxy",
            "type": "object",
            "description": "Proxy used when scraping Gratka. Default: no proxy (Gratka doesn't require it)."
          },
          "olxProxy": {
            "title": "OLX proxy",
            "type": "object",
            "description": "Proxy used when scraping OLX. Default: no proxy (OLX doesn't require it)."
          },
          "nolProxy": {
            "title": "Nieruchomości-online proxy",
            "type": "object",
            "description": "Proxy used when scraping Nieruchomości-online. Default: no proxy (NoL doesn't require it)."
          },
          "adresowoProxy": {
            "title": "Adresowo proxy",
            "type": "object",
            "description": "Proxy used when scraping Adresowo. Default: no proxy (Adresowo doesn't require it)."
          },
          "domiportaProxy": {
            "title": "Domiporta proxy",
            "type": "object",
            "description": "Proxy used when scraping Domiporta. Default: no proxy (Domiporta doesn't require it)."
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}