{
  "openapi": "3.0.1",
  "info": {
    "title": "Pige Immo FR: LBC + SeLoger + PAP + Bien'ici Multi-Source",
    "description": "Multi-source French real-estate pige: Leboncoin, SeLoger, Bien'ici, PAP, Logic-immo in one run. Auto-deduplication, ADEME DPE enrichment, GPS, price per m², owner-vs-agency flag. Filter by transaction, city, type, price, surface. For pige software, agents, hunters, marchands. $5/1K listings.",
    "version": "1.0",
    "x-build-id": "OHKBluObUfRYEtGy2"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/dltik~pige-immo-fr-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-dltik-pige-immo-fr-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/dltik~pige-immo-fr-scraper/runs": {
      "post": {
        "operationId": "runs-sync-dltik-pige-immo-fr-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/dltik~pige-immo-fr-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-dltik-pige-immo-fr-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": {
          "sources": {
            "title": "Sources to scrape",
            "type": "array",
            "description": "Subset of: pap, bienici (HTTP, no proxy needed); leboncoin, seloger, logic_immo (require Residential proxy + Playwright).",
            "items": {
              "type": "string"
            },
            "default": [
              "pap",
              "bienici"
            ]
          },
          "startUrls": {
            "title": "Leboncoin start URLs (optional)",
            "type": "array",
            "description": "Ready-made Leboncoin search URLs you have already geo-scoped, e.g. https://www.leboncoin.fr/recherche?category=9&locations=Roubaix__50.69_3.18_10000 . When set, the Leboncoin source scrapes these URLs directly and the cities/postalCodes/departments filters below are IGNORED for Leboncoin (you scoped the URL yourself); 'leboncoin' is auto-added to sources. Use the /recherche path — the /c/ path does NOT geo-filter.",
            "default": [],
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "transaction": {
            "title": "Transaction",
            "enum": [
              "buy",
              "rent"
            ],
            "type": "string",
            "description": "buy = vente, rent = location.",
            "default": "buy"
          },
          "cities": {
            "title": "Cities",
            "type": "array",
            "description": "City names. Example: ['Roubaix','Lyon']. Narrowest geo wins: if you also pass departments, results are trimmed to these cities (not the whole department).",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "postalCodes": {
            "title": "Postal codes",
            "type": "array",
            "description": "5-digit postal codes. Example: ['59390','59100']. Narrowest geo wins: if you also pass departments, results are trimmed to exactly these postal codes.",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "departments": {
            "title": "Department codes",
            "type": "array",
            "description": "2-digit department codes. Example: ['75','69','13']. Used alone = the whole department; combined with cities/postalCodes it only broadens the search that is then trimmed to those cities/postal codes.",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "radiusKm": {
            "title": "Search radius around town (km) — Leboncoin",
            "minimum": 1,
            "maximum": 200,
            "type": "integer",
            "description": "Optional. With a single city or postal code, Leboncoin searches within this radius (km) around that town — ideal for 'a handful of communes around a town'. Leave empty to match the exact commune(s) / postal code(s) only."
          },
          "propertyTypes": {
            "title": "Property types",
            "type": "array",
            "description": "Subset of: appartement, maison, terrain, parking, local, loft, chateau.",
            "items": {
              "type": "string"
            },
            "default": [
              "appartement"
            ]
          },
          "priceMin": {
            "title": "Min price (€)",
            "minimum": 0,
            "type": "integer",
            "description": "Minimum listing price in euros."
          },
          "priceMax": {
            "title": "Max price (€)",
            "minimum": 0,
            "type": "integer",
            "description": "Maximum listing price in euros."
          },
          "surfaceMin": {
            "title": "Min surface (m²)",
            "minimum": 0,
            "type": "integer",
            "description": "Minimum living area in m²."
          },
          "surfaceMax": {
            "title": "Max surface (m²)",
            "minimum": 0,
            "type": "integer",
            "description": "Maximum living area in m²."
          },
          "roomsMin": {
            "title": "Min rooms",
            "minimum": 1,
            "type": "integer",
            "description": "Minimum number of rooms."
          },
          "roomsMax": {
            "title": "Max rooms",
            "minimum": 1,
            "type": "integer",
            "description": "Maximum number of rooms."
          },
          "bedroomsMin": {
            "title": "Min bedrooms",
            "minimum": 0,
            "type": "integer",
            "description": "Minimum number of bedrooms."
          },
          "onlyOwner": {
            "title": "Owner-only listings (no agency)",
            "type": "boolean",
            "description": "Restrict to particulier (PAP all owner; LBC private filter).",
            "default": false
          },
          "newOnly": {
            "title": "New builds only",
            "type": "boolean",
            "description": "Restrict to programmes neufs (new construction).",
            "default": false
          },
          "onlyWithPhotos": {
            "title": "Only listings with photos",
            "type": "boolean",
            "description": "Skip listings without photos.",
            "default": false
          },
          "publishedWithinHours": {
            "title": "Only listings published in the last N hours",
            "minimum": 1,
            "type": "integer",
            "description": "Keep only listings FIRST published within the last N hours (filters on the original publication date, not the re-index/bump date). Great for daily/2x-day monitoring and to avoid paying for republished agency listings. Leave empty for no time filter."
          },
          "fetchDescriptions": {
            "title": "Fetch full descriptions (Leboncoin)",
            "type": "boolean",
            "description": "Fetch the full ad description text for Leboncoin listings. Leboncoin only returns the description on the detail page, so this adds one extra request per listing (slower + more bandwidth) — enable it when you need the description for keyword filtering. SeLoger descriptions are always included.",
            "default": false
          },
          "enrichDpe": {
            "title": "Enrich with ADEME DPE",
            "type": "boolean",
            "description": "When source doesn't return DPE, look up the official ADEME database by address+postal+surface match.",
            "default": true
          },
          "enrichDvf": {
            "title": "DVF price benchmark (find under-priced listings)",
            "type": "boolean",
            "description": "Benchmark each listing against real recorded sale prices (DVF open data) for the same commune and property type. Adds the local median €/m² (dvf_market_price_per_m2), how far the listing sits above/below it (dvf_price_vs_market_pct), and a deal flag (underpriced / market / overpriced). An owner listing priced below market is the hottest prospecting lead. Billed per listing benchmarked.",
            "default": false
          },
          "dedupAcrossSources": {
            "title": "Dedup across sources",
            "type": "boolean",
            "description": "Same property listed on LBC + SeLoger? Merge into one record (keep most-complete).",
            "default": true
          },
          "incremental": {
            "title": "Incremental mode (only new / price-changed listings)",
            "type": "boolean",
            "description": "Daily-monitoring mode. The actor remembers every listing it returned in your previous runs (in its own persistent storage) and returns ONLY listings that are new since last run, or whose price changed. Listings that sat online unchanged are skipped and NOT charged — no need to feed anything back. Works on ALL sources (matches the stable listing_key, not the publication date), so it catches even PAP / re-bumped agency mandates that publishedWithinHours misses. Leave off for a full one-shot scrape.",
            "default": false
          },
          "detectPriceChanges": {
            "title": "Return price-changed listings (incremental mode)",
            "type": "boolean",
            "description": "In incremental mode, still return a previously-seen listing when its price moved since last run — flagged with price_changed=true and previous_price. Turn off to get strictly-new listings only. Ignored when incremental is off.",
            "default": true
          },
          "excludeIds": {
            "title": "Exclude already-seen listings (IDs / URLs)",
            "type": "array",
            "description": "Stateless alternative to incremental mode: paste the listing_key values (or URLs) you already retrieved in a previous run — matching listings are skipped and NOT charged. Every output record includes a listing_key field; collect them and feed them back here next run. Use this if you keep your own database instead of relying on the actor's built-in memory.",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "maxResultsPerSource": {
            "title": "Max results per source",
            "minimum": 1,
            "maximum": 5000,
            "type": "integer",
            "description": "Each enabled source will return up to this many listings. Aliases accepted: 'limit', 'max', 'maxResults'. Each listing is charged at the per-event price — start small (e.g. 20) to validate output before scaling up.",
            "default": 20
          },
          "customProxyUrl": {
            "title": "Custom proxy URL (optional — overrides Apify proxy)",
            "type": "string",
            "description": "Optional external residential/mobile FR proxy URL (http://user:pass@host:port). Overrides the Apify proxy for ALL sources. Use this when Apify's shared RESIDENTIAL pool gets DataDome-blocked on Leboncoin — a dedicated/cleaner FR pool passes far more reliably. Sticky-session providers (a session-<token> in the credentials) are auto-rotated on a block. Example: http://user:pass_country-FR_session-abc_lifetime-1440@proxies.example.com:1000"
          },
          "proxyConfig": {
            "title": "Proxy (Residential required for LBC/SeLoger/Logic-immo)",
            "type": "object",
            "description": "Apify proxy. Default datacenter works for HTTP sources (PAP, Bien'ici). Switch to RESIDENTIAL with apifyProxyCountry='FR' for DataDome/PerimeterX bypass on LBC, SeLoger, Logic-immo. Ignored when customProxyUrl is set.",
            "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}