# Kleinanzeigen Deal Finder & Price Monitor (`ninhothedev/kleinanzeigen-deal-finder`) Actor

$2/1K 🔥 Kleinanzeigen DEAL FINDER for Germany 🇩🇪! Auto-spot underpriced listings vs. market median — flip, resell & profit. Title, price, deal-score, location & images. JSON, CSV, Excel or API. Paste a search URL & surface bargains instantly ⚡

- **URL**: https://apify.com/ninhothedev/kleinanzeigen-deal-finder.md
- **Developed by:** [ninhothedev](https://apify.com/ninhothedev) (community)
- **Categories:** E-commerce, Automation, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 new listing scrapeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Kleinanzeigen Deal Finder & Price Monitor

**Monitor Kleinanzeigen.de (eBay Kleinanzeigen) searches and get instant alerts on underpriced listings.** This Kleinanzeigen scraper watches your searches, detects new listings the moment they appear, computes a **deal score** against the live market median, and flags the bargains — built for **resellers, flippers and price monitoring**.

Point it at any Kleinanzeigen search URL (iPhones, consoles, GPUs, furniture, car parts — anything), put it on a 15‑minute schedule, and let the deals come to you.

---

> ## ⚠️ Read this first: use a SEARCH URL, not a single listing
>
> Paste a **search‑results** URL — open [kleinanzeigen.de](https://www.kleinanzeigen.de), type your keyword, set your filters, then copy the URL from the address bar:
>
> ✅ **Correct:** `https://www.kleinanzeigen.de/s-rolex-gmt-master/k0`
> ❌ **Wrong:** `https://www.kleinanzeigen.de/s-anzeige/rolex-.../3442016963-157-1001`
>
> The wrong one is a **single ad page** (`/s-anzeige/…`), not a search. If you paste that, the actor **stops immediately with a clear error** instead of returning unrelated listings — so you can't get garbage results by accident. Fix the URL and re‑run.

---

### How to get your search URL (30 seconds)

1. Open **[kleinanzeigen.de](https://www.kleinanzeigen.de)**.
2. Type your keyword into the **search bar** (e.g. `Rolex GMT Master 2`) and press **Enter**. You're now on a **results page**.
3. *(Optional but recommended)* narrow it with the filters on that page — **category**, **location + radius**, **price range (Preis von–bis)**, **„Nur Privat"**. Every filter you set is baked into the URL.
4. Copy the **whole URL from your browser's address bar**.
5. Paste it into the **`searchUrls`** field. Add several to monitor multiple markets.

**Example:** `https://www.kleinanzeigen.de/s-rolex-gmt-master/k0` — keyword search, all of Germany.

> 💡 The more specific the search (keyword + price range), the **sharper the deal detection** — a tight search gives a clean market median to compare against. For phones/consoles, include the storage (e.g. `iPhone 13 128GB`) so the variant clustering kicks in.

---

### Why resellers use it

Most "deal finders" just dump every cheap listing on you. This one is built to surface **real** bargains and to keep running unattended:

- 🎯 **Smart deal score, not a dumb price filter** — every new listing is scored against a *clean* market median (variant‑clustered, outlier‑trimmed, scam‑floored), so you get genuine underpriced ads, not noise. See [How the deal score works](#how-the-deal-score-works).
- 🆕 **Only new listings** — it remembers what it has already seen, so each run returns just what appeared since last time. No duplicate spam.
- ⚡ **Catch deals first** — freshly posted, underpriced ads are flagged within minutes, so you can message the seller before anyone else.
- 📉 **Price‑drop tracking** — remembers each listing's price across runs and flags cuts (`priceDropped`, `priceDropPercent`) — a strong buy signal even on older ads.
- 🔁 **eBay margin (optional)** — compares each deal against eBay.de **sold** prices so you see your real flip margin, not just the Kleinanzeigen median.
- 🛡️ **Reliable & hard to block** — Chrome‑fingerprint requests + Apify proxies + a browser fallback. If the site layout changes, the run **fails loudly** instead of returning junk.
- 🧹 **Clean results** — automatically drops Kleinanzeigen's loosely‑related "ähnliche Anzeigen" padding, so a niche search stays on‑topic.
- 💸 **Predictable cost** — pay‑per‑event (cents), and the market median is **cached between runs** so high‑frequency monitoring stays cheap. No surprise bills.
- 🔔 **Set & forget** — runs on an Apify Schedule and pushes deals to Slack / WhatsApp / Make / Zapier / n8n. Export to JSON, CSV, Excel or API.
- 🔒 **GDPR‑conscious** — listing data only; it never extracts phone numbers or e‑mail addresses.

---

### Example output

Each new listing becomes one dataset item:

```json
{
  "id": "2845673921",
  "title": "iPhone 13 128GB Blau",
  "price": 320,
  "currency": "EUR",
  "isVB": true,
  "medianPrice": 465,
  "percentBelowMarket": 31,
  "dealScore": 31,
  "isDeal": true,
  "url": "https://www.kleinanzeigen.de/s-anzeige/iphone-13-128gb-blau/2845673921-173-3508",
  "imageUrl": "https://img.kleinanzeigen.de/api/v1/prod-ads/images/...",
  "location": "Berlin Mitte",
  "zipCode": "10115",
  "postedAt": "2026-06-12T09:41:00Z",
  "listingAgeHours": 0.4,
  "sellerType": "private",
  "shippingAvailable": true,
  "searchUrl": "https://www.kleinanzeigen.de/s-handy-telefon/iphone-13/k0c173"
}
````

With `fetchDetails: true` you also get `description`, `allImages[]`, `sellerName`, `sellerActiveSince` and `sellerListingCount`.

***

### How to set up monitoring (3 steps)

This actor does **one pass per run**. The monitoring loop is a native Apify **Schedule** — set it up once:

1. **Run the actor once** with your `searchUrls` to confirm it returns listings (the first run per search is an *initial baseline* and returns everything currently live).
2. In the Apify Console go to **Schedules → Create schedule**, add this actor/task, and set the interval to **every 15 minutes** (power users: 5 minutes).
3. Save. From now on each scheduled run returns **only new listings** since the last run.

***

### 🔔 Get instant deal alerts (3 steps)

Alerts run through Apify's native integrations — no extra config in the actor:

1. **Create the schedule** above (15 min recommended).
2. Open the actor/task → **Integrations** tab → add **Webhook**, **Slack**, **Make**, **Zapier** or **n8n**.
3. Set the trigger to **“Run succeeded.”** Every dataset item carries all fields you need — filter on `isDeal: true` in your integration and push the `url` straight to your phone.

Tip: in Make/Zapier, add a filter `isDeal = true` so you're only pinged on real bargains, not every new listing.

***

### Pricing example

This actor uses **pay‑per‑event**. You pay for what it finds:

| Event | When | Price |
|---|---|---|
| `listing-scraped` | per new listing detected | $0.002 |
| `deal-found` | per listing flagged as a deal | $0.05 |
| `detail-enriched` | per detail page fetched (`fetchDetails`) | $0.005 |

**Worked example:** 3 searches, 15‑minute schedule, ~40 new listings/day total, ~2 deals/day:

- New listings: 40 × 30 days × $0.002 ≈ **$2.40/mo**
- Deals: 2 × 30 days × $0.05 ≈ **$3.00/mo**
- **≈ $5–6/month** to monitor 3 markets around the clock. One good flip pays for a year.

(Prices shown are examples — see the actor's pricing tab for current rates.)

***

### Settings — everything you can configure

| Field | Type | Default | What it does |
|---|---|---|---|
| `searchUrls` | array | iPhone example | One or more Kleinanzeigen **search‑results** URLs (filters baked into the URL). Each is monitored independently. Soft limit 10. |
| `dealThresholdPercent` | integer | `25` | A listing is a deal when its price is **at least this %** below the market median. |
| `maxListingAgeHours` | integer | `6` | Only listings **younger than this** can be flagged as deals. Older ones are still scraped, never flagged. |
| `privateOnly` | boolean | `false` | Keep only **private** sellers (drop commercial / PRO). |
| `fetchDetails` | boolean | `false` | Also load each new listing's **detail page** (full description, all photos, seller profile). |
| `maxItemsPerSearch` | integer | `100` | Max **new** listings pushed per search (caps cost on broad searches). |
| `medianBasisDepth` | integer | `100` | How many listings are scanned to build the median on a **refresh** run. |
| `medianRefreshEveryRuns` | integer | `6` | Refresh the cached median **every N runs** (light scans in between → cheaper, gentler monitoring). |
| `compareEbaySold` | boolean | `false` | For each deal, attach the **eBay.de sold‑price** median + estimated margin. |
| `proxyConfiguration` | object | Apify Datacenter | Standard Apify proxy input. Datacenter is enough for most searches. |

#### How to tune the main settings

- **`dealThresholdPercent` (how cheap = a deal):** `25` is a sensible default. Lower it (e.g. `15`) to catch smaller bargains and get more alerts; raise it (e.g. `40`) for only the strong steals. For high‑variance markets (watches, cars) keep it higher to avoid noise.
- **`maxListingAgeHours` (how fresh):** `6` is built for "be first" sniping. **Raise it to `168` (7 days) or `720` (30 days)** when you want to surface *existing* underpriced listings (e.g. a one‑off scan or a demo), not just brand‑new ones.
- **`privateOnly`:** turn **on** for flipping — private sellers are where the bargains are; commercial/PRO sellers usually price at market.
- **`fetchDetails`:** **off** for high‑frequency monitoring (faster, cheaper). **On** for research runs when you want full descriptions, every photo and the seller profile. Adds a small per‑item charge.
- **`medianRefreshEveryRuns`:** higher = cheaper and gentler on Kleinanzeigen (the median barely moves between runs). On a 5‑minute schedule, `6` refreshes the benchmark roughly every 30 minutes.
- **`compareEbaySold`:** turn **on** for flipping to see cross‑platform margin. It only runs on flagged deals, so it stays cheap.

> Need help building the URL? See **[How to get your search URL](#how-to-get-your-search-url-30-seconds)** above.

***

### How the deal score works

This is what sets it apart from a plain scraper. The score is built on a **clean, like‑for‑like comparison basis**, not a naive average of everything in the search:

- **Variant clustering** — a 128 GB phone is compared against other 128 GB phones, a 256 GB against 256 GB. Storage/variant is parsed from each title so different configurations don't pollute each other's median.
- **Noise removed from the benchmark** — paid TOP ads, "wanted / Ankauf / Suche" ads, **defective / for‑parts** listings, accessories (cases, cables, glass) and pure‑VB / €1 placeholders are all excluded before the median is computed.
- **Outlier trimming** — the lowest and highest 10% of prices are dropped.
- **Scam floor** — anything priced *absurdly* low (>75% below median) is flagged `suspiciousTooCheap` instead of being celebrated as a deal, so you aren't pinged on bait listings.
- **Minimum basis** — at least 5 comparable offers (4 for a variant cluster) are required before any deal is flagged; thin searches never produce false positives.
- **Price‑drop tracking** — the last seen price per listing is remembered between runs. A price cut sets `priceDropped: true` and `priceDropPercent` — a strong standalone buy signal.

`dealScore` = percent below the chosen median. `isDeal` is true when `dealScore ≥ dealThresholdPercent`, the listing is a working offer (`condition: normal`, `intent: offer`), younger than `maxListingAgeHours`, and not below the scam floor. Each item shows what it was compared against via `medianBasis` (`variant:128gb` or `global`) and `medianSampleSize`.

- **Cached benchmark** — the market median moves slowly, so it's cached between runs and only refreshed every `medianRefreshEveryRuns` runs. In-between runs do a light scan that's enough to catch new listings, so a 5‑minute schedule stays cheap and gentle on Kleinanzeigen.

#### eBay sold‑price comparison (cross‑platform margin)

Enable `compareEbaySold` and every flagged deal also gets looked up against **eBay.de sold & completed** listings. You get:

- `ebaySoldMedian` — the trimmed median of what the item actually *sold* for on eBay
- `ebaySoldSampleSize` — how many sold results backed that median
- `ebayMarginPercent` — how far the eBay sold median sits **above** the Kleinanzeigen price (your estimated gross margin)

It runs only on deals (rare → cheap) and is **best‑effort**: eBay has its own anti‑bot and changes its markup, so if a lookup fails the deal is still returned, just without the eBay fields.

***

### FAQ

**Does it need proxies?** Apify Datacenter proxy (the default) is enough for most searches. Switch to Residential only if you see blocks.

**How often should it run?** 15 minutes is a good balance of freshness and cost. Drop to 5 minutes for hot, fast‑moving categories.

**Will I get duplicates?** No. Seen listing IDs are stored between runs per search; only new listings are returned.

**Can I monitor several categories at once?** Yes — add multiple `searchUrls`. Each is tracked independently.

**Why is the first run so big?** The first run for a search is an initial baseline (`isInitialRun: true`) and returns everything currently live. Subsequent runs return only new listings.

***

### Legal & privacy

This actor collects only **publicly available listing data**. It does **not** extract phone numbers or e‑mail addresses. You are responsible for complying with Kleinanzeigen's Terms of Service and applicable data‑protection law (incl. GDPR) for your use case. Use scraped data responsibly.

***

**Keywords:** kleinanzeigen scraper, ebay kleinanzeigen, deal finder, price monitor, flipping, reseller, listing alerts, germany marketplace monitoring.

# Actor input Schema

## `searchUrls` (type: `array`):

One or more Kleinanzeigen.de SEARCH-RESULTS URLs (with all filters applied in the URL). Open kleinanzeigen.de, type your keyword, set filters (category, location, radius, price), then copy the URL from the address bar — e.g. https://www.kleinanzeigen.de/s-rolex-gmt-master/k0. ⚠️ Do NOT paste a single listing page (a /s-anzeige/... URL) — that is one ad, not a search, and will be rejected. Each search is monitored independently. Soft limit: 10 searches per run.

## `dealThresholdPercent` (type: `integer`):

A listing is flagged as a deal when its price is at least this many percent below the trimmed median price of comparable active listings in the same search.

## `maxListingAgeHours` (type: `integer`):

Only listings published within the last X hours can be flagged as deals. Lower = catch fresh deals before everyone else. Listings older than this are still scraped, just never marked as a deal.

## `privateOnly` (type: `boolean`):

When enabled, commercial / PRO sellers are excluded. Private sellers are usually where the real bargains are.

## `fetchDetails` (type: `boolean`):

Load each new listing's detail page for full description, all images and seller profile (active since, listing count). Slower and adds a per-item charge. Recommended OFF for high-frequency monitoring, ON for research runs.

## `compareEbaySold` (type: `boolean`):

For each flagged deal, also look up eBay.de sold/completed prices and attach the eBay sold median + estimated cross-platform margin (ebaySoldMedian, ebayMarginPercent). Best-effort and only run on deals, so it stays cheap. Adds a little time per deal.

## `maxItemsPerSearch` (type: `integer`):

Maximum number of NEW listings pushed to the dataset per search URL. Caps cost on very broad searches.

## `medianBasisDepth` (type: `integer`):

How many listings to scan per search to build the market median (the deal benchmark) on a refresh run. Higher = more robust deal scoring. Only NEW listings are pushed and charged; the rest are used purely to compute the median.

## `medianRefreshEveryRuns` (type: `integer`):

The market median changes slowly, so it is cached between runs. Only every Nth run does a full deep scan to refresh it; in-between runs do a light scan that's enough to catch new listings. Lower = fresher median but more requests. With a 5-minute schedule, 6 means refresh ~every 30 minutes.

## `proxyConfiguration` (type: `object`):

Proxy settings. Apify Datacenter proxy is enough for most searches; switch to Residential if you hit blocks.

## Actor input object example

```json
{
  "searchUrls": [
    "https://www.kleinanzeigen.de/s-handy-telefon/iphone-13/k0c173"
  ],
  "dealThresholdPercent": 25,
  "maxListingAgeHours": 6,
  "privateOnly": false,
  "fetchDetails": false,
  "compareEbaySold": false,
  "maxItemsPerSearch": 100,
  "medianBasisDepth": 100,
  "medianRefreshEveryRuns": 6,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": []
  }
}
```

# Actor output Schema

## `deals` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchUrls": [
        "https://www.kleinanzeigen.de/s-handy-telefon/iphone-13/k0c173"
    ],
    "dealThresholdPercent": 25,
    "maxListingAgeHours": 6,
    "maxItemsPerSearch": 100,
    "medianBasisDepth": 100,
    "medianRefreshEveryRuns": 6,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": []
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("ninhothedev/kleinanzeigen-deal-finder").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchUrls": ["https://www.kleinanzeigen.de/s-handy-telefon/iphone-13/k0c173"],
    "dealThresholdPercent": 25,
    "maxListingAgeHours": 6,
    "maxItemsPerSearch": 100,
    "medianBasisDepth": 100,
    "medianRefreshEveryRuns": 6,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": [],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("ninhothedev/kleinanzeigen-deal-finder").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchUrls": [
    "https://www.kleinanzeigen.de/s-handy-telefon/iphone-13/k0c173"
  ],
  "dealThresholdPercent": 25,
  "maxListingAgeHours": 6,
  "maxItemsPerSearch": 100,
  "medianBasisDepth": 100,
  "medianRefreshEveryRuns": 6,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": []
  }
}' |
apify call ninhothedev/kleinanzeigen-deal-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=ninhothedev/kleinanzeigen-deal-finder",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Kleinanzeigen Deal Finder & Price Monitor",
        "description": "$2/1K 🔥 Kleinanzeigen DEAL FINDER for Germany 🇩🇪! Auto-spot underpriced listings vs. market median — flip, resell & profit. Title, price, deal-score, location & images. JSON, CSV, Excel or API. Paste a search URL & surface bargains instantly ⚡",
        "version": "0.0",
        "x-build-id": "SRrjncqb58pCCcZVn"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/ninhothedev~kleinanzeigen-deal-finder/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-ninhothedev-kleinanzeigen-deal-finder",
                "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/ninhothedev~kleinanzeigen-deal-finder/runs": {
            "post": {
                "operationId": "runs-sync-ninhothedev-kleinanzeigen-deal-finder",
                "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/ninhothedev~kleinanzeigen-deal-finder/run-sync": {
            "post": {
                "operationId": "run-sync-ninhothedev-kleinanzeigen-deal-finder",
                "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",
                "required": [
                    "searchUrls"
                ],
                "properties": {
                    "searchUrls": {
                        "title": "Search URLs",
                        "type": "array",
                        "description": "One or more Kleinanzeigen.de SEARCH-RESULTS URLs (with all filters applied in the URL). Open kleinanzeigen.de, type your keyword, set filters (category, location, radius, price), then copy the URL from the address bar — e.g. https://www.kleinanzeigen.de/s-rolex-gmt-master/k0. ⚠️ Do NOT paste a single listing page (a /s-anzeige/... URL) — that is one ad, not a search, and will be rejected. Each search is monitored independently. Soft limit: 10 searches per run.",
                        "default": [
                            "https://www.kleinanzeigen.de/s-handy-telefon/iphone-13/k0c173"
                        ],
                        "items": {
                            "type": "string"
                        }
                    },
                    "dealThresholdPercent": {
                        "title": "Deal threshold (% below median)",
                        "minimum": 1,
                        "maximum": 90,
                        "type": "integer",
                        "description": "A listing is flagged as a deal when its price is at least this many percent below the trimmed median price of comparable active listings in the same search.",
                        "default": 25
                    },
                    "maxListingAgeHours": {
                        "title": "Max listing age (hours)",
                        "minimum": 1,
                        "maximum": 168,
                        "type": "integer",
                        "description": "Only listings published within the last X hours can be flagged as deals. Lower = catch fresh deals before everyone else. Listings older than this are still scraped, just never marked as a deal.",
                        "default": 6
                    },
                    "privateOnly": {
                        "title": "Private sellers only",
                        "type": "boolean",
                        "description": "When enabled, commercial / PRO sellers are excluded. Private sellers are usually where the real bargains are.",
                        "default": false
                    },
                    "fetchDetails": {
                        "title": "Fetch listing details",
                        "type": "boolean",
                        "description": "Load each new listing's detail page for full description, all images and seller profile (active since, listing count). Slower and adds a per-item charge. Recommended OFF for high-frequency monitoring, ON for research runs.",
                        "default": false
                    },
                    "compareEbaySold": {
                        "title": "Compare against eBay sold prices",
                        "type": "boolean",
                        "description": "For each flagged deal, also look up eBay.de sold/completed prices and attach the eBay sold median + estimated cross-platform margin (ebaySoldMedian, ebayMarginPercent). Best-effort and only run on deals, so it stays cheap. Adds a little time per deal.",
                        "default": false
                    },
                    "maxItemsPerSearch": {
                        "title": "Max new items to push per search",
                        "minimum": 1,
                        "maximum": 1000,
                        "type": "integer",
                        "description": "Maximum number of NEW listings pushed to the dataset per search URL. Caps cost on very broad searches.",
                        "default": 100
                    },
                    "medianBasisDepth": {
                        "title": "Median basis depth",
                        "minimum": 25,
                        "maximum": 500,
                        "type": "integer",
                        "description": "How many listings to scan per search to build the market median (the deal benchmark) on a refresh run. Higher = more robust deal scoring. Only NEW listings are pushed and charged; the rest are used purely to compute the median.",
                        "default": 100
                    },
                    "medianRefreshEveryRuns": {
                        "title": "Refresh median every N runs",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "The market median changes slowly, so it is cached between runs. Only every Nth run does a full deep scan to refresh it; in-between runs do a light scan that's enough to catch new listings. Lower = fresher median but more requests. With a 5-minute schedule, 6 means refresh ~every 30 minutes.",
                        "default": 6
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Proxy settings. Apify Datacenter proxy is enough for most searches; switch to Residential if you hit blocks.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": []
                        }
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
