{
  "openapi": "3.0.1",
  "info": {
    "title": "Kleinanzeigen Deal Monitor — New Ads, Price Drops & Alerts",
    "description": "Monitor Kleinanzeigen.de searches: new ads, price drops, free items and underpriced deals near you, with scam-risk flags and Telegram or webhook alerts. Pay only for new rows. JSON, CSV, API, MCP.",
    "version": "0.1",
    "x-build-id": "RtkSUXWceJYtgabra"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/kondasviktor~kleinanzeigen-deal-monitor/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-kondasviktor-kleinanzeigen-deal-monitor",
        "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/kondasviktor~kleinanzeigen-deal-monitor/runs": {
      "post": {
        "operationId": "runs-sync-kondasviktor-kleinanzeigen-deal-monitor",
        "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/kondasviktor~kleinanzeigen-deal-monitor/run-sync": {
      "post": {
        "operationId": "run-sync-kondasviktor-kleinanzeigen-deal-monitor",
        "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": {
          "mode": {
            "title": "Mode",
            "enum": [
              "monitor",
              "snapshot"
            ],
            "type": "string",
            "description": "`monitor` writes (and charges) only new or changed ads and sends alerts — schedule it every 15–60 minutes. `snapshot` exports every ad it finds, once.",
            "default": "monitor"
          },
          "searches": {
            "title": "Searches",
            "type": "array",
            "description": "Your saved searches. Each: `{ \"name\": \"E-Bike München\", \"query\": \"e-bike\", \"postcode\": \"80331\", \"radiusKm\": 30, \"priceMin\": 300, \"priceMax\": 2000, \"sellerType\": \"private\", \"shippingOnly\": false, \"buyNowOnly\": false, \"categoryId\": 217, \"conditions\": [], \"mustInclude\": [], \"mustExclude\": [\"akku\"] }`. Only `query` (or a `categoryId`) is required; everything else falls back to the global fields below. One search = one paid \"tracked search\" per run."
          },
          "searchUrls": {
            "title": "Kleinanzeigen search URLs",
            "type": "array",
            "description": "Paste search result URLs from kleinanzeigen.de (https://www.kleinanzeigen.de/s-…). Keyword, category, place, radius, price and seller filters are read from each URL. This is the most reliable way to describe a search.",
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "homePostcode": {
            "title": "Your postcode",
            "type": "string",
            "description": "5-digit German postcode. Every ad gets `distanceKm` from here, and `maxDistanceKm` filters by it."
          },
          "maxDistanceKm": {
            "title": "Maximum distance (km)",
            "minimum": 1,
            "type": "integer",
            "description": "Drop ads farther than this from your postcode (works across several searches). Ads whose postcode is unknown are kept unless you tick the option below."
          },
          "dropUnknownDistance": {
            "title": "Drop ads with unknown distance",
            "type": "boolean",
            "description": "With a maximum distance set, also drop ads whose postcode could not be located.",
            "default": false
          },
          "sellerType": {
            "title": "Seller type",
            "enum": [
              "any",
              "private",
              "commercial"
            ],
            "type": "string",
            "description": "Private sellers only, commercial sellers only, or both.",
            "default": "any"
          },
          "adType": {
            "title": "Ad type",
            "enum": [
              "offer",
              "wanted",
              "any"
            ],
            "type": "string",
            "description": "Offers (Angebote) by default; wanted ads (Gesuche) are excluded unless you choose them.",
            "default": "offer"
          },
          "priceTypes": {
            "title": "Price types",
            "type": "array",
            "description": "Fixed price (Festpreis), negotiable (VB), free (zu verschenken), on request (auf Anfrage / no price). Choose only `free` to watch the free-items category.",
            "items": {
              "type": "string",
              "enum": [
                "fixed",
                "negotiable",
                "free",
                "on_request"
              ],
              "enumTitles": [
                "Fixed price (Festpreis)",
                "Negotiable (VB)",
                "Free (zu verschenken)",
                "On request / no price"
              ]
            },
            "default": [
              "fixed",
              "negotiable",
              "free",
              "on_request"
            ]
          },
          "conditions": {
            "title": "Conditions",
            "type": "array",
            "description": "Ads whose condition is outside this list are dropped. The condition is judged from the title on search results (\"defekt\", \"Bastler\") and from the ad page when ad details are on. Defective ads are off by default — add `defective` for repair flipping.",
            "items": {
              "type": "string",
              "enum": [
                "new",
                "like_new",
                "very_good",
                "good",
                "acceptable",
                "defective",
                "unknown"
              ],
              "enumTitles": [
                "New (Neu)",
                "Like new (Wie neu)",
                "Very good (Sehr gut)",
                "Good (Gut)",
                "Acceptable (In Ordnung)",
                "Defective (Defekt) — for repair flippers",
                "Condition not shown in the list"
              ]
            },
            "default": [
              "new",
              "like_new",
              "very_good",
              "good",
              "acceptable",
              "unknown"
            ]
          },
          "includeTopAds": {
            "title": "Include Top ads",
            "type": "boolean",
            "description": "Top / sponsored ads are pinned above the results on every page. They are always flagged (`isTopAd`) and never count as NEW; tick this to write them as rows anyway.",
            "default": false
          },
          "excludeJunk": {
            "title": "Remove junk",
            "type": "boolean",
            "description": "Removes accessories (Hülle, Case, Schutzfolie, Panzerglas, Ladekabel), wanted/swap posts (Suche, Tausche, gesucht), empty boxes (nur Karton, OVP leer) and spare parts (Ersatzteil). Keeps deal medians clean. A search for the accessory itself keeps it.",
            "default": true
          },
          "mustInclude": {
            "title": "Must include (all)",
            "type": "array",
            "description": "Every term must appear in the ad title (and description when ad details are on). Case- and accent-insensitive.",
            "items": {
              "type": "string"
            }
          },
          "mustExclude": {
            "title": "Must exclude (any)",
            "type": "array",
            "description": "Drop ads containing any of these terms. Extends the junk filter.",
            "items": {
              "type": "string"
            }
          },
          "excludeSellerIds": {
            "title": "Excluded seller IDs",
            "type": "array",
            "description": "Block known relisters or dealers by the `sellerId` shown in the results.",
            "items": {
              "type": "string"
            }
          },
          "maxItemsPerSearch": {
            "title": "Max ads per search",
            "minimum": 1,
            "maximum": 10000,
            "type": "integer",
            "description": "Stops paging after this many ads (Top ads don't count). Also your cost cap. Kleinanzeigen shows at most 1,250 results per search; above that the Actor splits the price range into bands and reports the coverage.",
            "default": 200
          },
          "alertOn": {
            "title": "Alert on",
            "type": "array",
            "description": "Events that trigger Telegram / webhook alerts. The first run of a monitor is its baseline: existing ads are written but not announced as new or free.",
            "items": {
              "type": "string",
              "enum": [
                "NEW",
                "PRICE_DROP",
                "DEAL",
                "FREE_ITEM",
                "LIKELY_SOLD_OR_REMOVED"
              ],
              "enumTitles": [
                "New ad",
                "Price drop",
                "Deal (below market)",
                "Free item (zu verschenken)",
                "Likely sold or removed"
              ]
            },
            "default": [
              "DEAL",
              "PRICE_DROP",
              "FREE_ITEM"
            ]
          },
          "dealThresholdPct": {
            "title": "Deal threshold (% below median)",
            "minimum": 1,
            "maximum": 99,
            "type": "number",
            "description": "An ad is a DEAL when it is at least this much cheaper than the median asking price of similar ads (outliers, junk and free ads removed).",
            "default": 30
          },
          "minCompsForDeal": {
            "title": "Minimum comparable ads",
            "minimum": 3,
            "type": "integer",
            "description": "A deal verdict needs at least this many similar ads (8 = `medium` confidence). Fewer gives `compsConfidence: low`.",
            "default": 8
          },
          "priceDropThresholdPct": {
            "title": "Price drop threshold (%)",
            "minimum": 1,
            "maximum": 99,
            "type": "number",
            "description": "Report a PRICE_DROP when an ad's price fell by at least this much since last seen.",
            "default": 10
          },
          "hideHighScamRisk": {
            "title": "Hide high scam risk",
            "type": "boolean",
            "description": "Drop ads scored `high` instead of just flagging them. Scam flags are heuristics to prioritise your checks, not a verdict about any seller.",
            "default": false
          },
          "includeItemDetails": {
            "title": "Include ad details",
            "type": "boolean",
            "description": "Opens the ad page of every row it writes: description, condition, all attributes, seller account age and badges. Enables the new-account and contact-outside-platform scam checks. Charged as `item-details` ($0.002 per ad) — failed pages are free.",
            "default": false
          },
          "alertLanguage": {
            "title": "Alert language",
            "enum": [
              "en",
              "de",
              "hu"
            ],
            "type": "string",
            "description": "Language of the Telegram messages.",
            "default": "en"
          },
          "telegramBotToken": {
            "title": "Telegram bot token",
            "type": "string",
            "description": "From @BotFather (`/newbot`). Looks like `123456:ABC-DEF…`."
          },
          "telegramChatId": {
            "title": "Telegram chat ID",
            "type": "string",
            "description": "Message your bot once, then get your chat ID (for example from @userinfobot)."
          },
          "webhookUrl": {
            "title": "Webhook URL",
            "type": "string",
            "description": "Receives one JSON POST per run with all alert events. HTTPS only; private addresses are refused."
          },
          "webhookSecret": {
            "title": "Webhook secret",
            "type": "string",
            "description": "Optional. Adds an `X-Signature: sha256=…` HMAC header so you can verify the sender."
          },
          "maxAlertsPerRun": {
            "title": "Max alerts per run",
            "minimum": 1,
            "type": "integer",
            "description": "Above this many alerts Telegram gets one digest message instead.",
            "default": 20
          },
          "monitorId": {
            "title": "Monitor ID",
            "type": "string",
            "description": "Names the state store that remembers which ads were seen. Keep it stable across scheduled runs; by default it is derived from your searches."
          },
          "proxyConfiguration": {
            "title": "Proxy for blocked requests",
            "type": "object",
            "description": "Requests go out directly from the Apify platform first. Only when Kleinanzeigen keeps blocking that IP does the Actor switch to this proxy (residential, Germany) and stay on it for the rest of the run. Datacenter proxies are never used — Kleinanzeigen bans them. Turn Apify proxy off to forbid any escalation.",
            "default": {
              "useApifyProxy": true,
              "apifyProxyGroups": [
                "RESIDENTIAL"
              ],
              "apifyProxyCountry": "DE"
            }
          },
          "alwaysUseProxy": {
            "title": "Always use the proxy",
            "type": "boolean",
            "description": "Skip the direct attempt and send every request through the proxy above. Only needed if direct requests from Apify are blocked for you — it uses (paid) residential bandwidth.",
            "default": false
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}