# ProvenExpert Reviews & DACH Reputation Monitor (`kamerozkan/provenexpert-reviews-scraper`) Actor

Unofficial scraper for public ProvenExpert, Trusted Shops, eKomi, and Google Maps reputation data. Match businesses, monitor changes, and benchmark DACH trust signals.

- **URL**: https://apify.com/kamerozkan/provenexpert-reviews-scraper.md
- **Developed by:** [Kamer Ozkan](https://apify.com/kamerozkan) (community)
- **Categories:** E-commerce, Lead generation, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $28.00 / 1,000 matched businesses

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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/docs.md):

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

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.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/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

## ProvenExpert Reviews & DACH Reputation Monitor

Extract public business ratings and reviews from ProvenExpert, Trusted Shops, eKomi, and Google Maps. Match the same company across channels, calculate a transparent DACH Trust Score, track changes over time, and benchmark each business against a supplied or discovered sector cohort.

> **Unofficial Actor:** This Actor is independently developed and is not affiliated with, endorsed by, or sponsored by ProvenExpert, Trusted Shops, eKomi, or Google.

The Actor works without login, cookies, paid APIs, or a dependency on another Apify Actor.

### What this Actor does

- Extracts ProvenExpert company profiles, ratings, recommendation rates, external sources, contact data, and native reviews.
- Extracts Trusted Shops profile data, certificate status, rating distribution, lifetime/current review counts, and per-review verification status when the API declares it.
- Extracts eKomi certificate data, rating basis, lifetime counts, positive/neutral/negative percentages, post-transaction reviews, order dates, and owner replies.
- Extracts Google Maps company, category, rating, review count when visible, website, phone, address, and coordinates.
- Follows supported external profile links found on ProvenExpert and refreshes those sources directly.
- Checks the company homepage once for supported review badge/profile links, without crawling the rest of the website.
- Matches profiles using explicit business groups, website domains, phones, company names, postal codes, and cities.
- Produces one cross-platform `business` row per matched company.
- Calculates a versioned DACH Trust Score from rating quality, volume, channel coverage, freshness, and source verification.
- Saves compact snapshots to a persistent time-series dataset and keeps an indexed latest-state store for fast comparisons at any history size.
- Supports `changesOnly` output for alerts, webhooks, and low-noise scheduled monitoring.
- Marks partial multi-source snapshots as `incomplete`; failed channels are never reported as removed and incomplete snapshots never advance history.
- Discovers ProvenExpert businesses by sector/keyword and location.
- Calculates sector rating, Trust Score, and review-volume percentiles from observed cohort data.

### Supported platforms

| Platform | Profile aggregate | Native reviews | Direct pagination | Verification field |
|---|---:|---:|---:|---|
| ProvenExpert | Yes | Yes | Yes | Source-declared policy |
| Trusted Shops | Yes | Yes | Yes | Per-review API status when declared |
| eKomi | Yes | Yes | Yes | Post-transaction collection policy |
| Google Maps | Yes | Aggregate only | Not applicable | Public reviews are not treated as verified |

Google Maps review text is intentionally outside this Actor's scope. The commercial differentiator is a normalized cross-channel business row, while specialist Google Maps Actors already cover high-volume Google review extraction.

### Result types

#### 1. Cross-platform business row

```json
{
  "type": "business",
  "entityKey": "business_673e011f616ad6f1f205",
  "companyName": "S&P Unternehmerforum GmbH",
  "category": "Seminare + Lehrgänge mit Zertifizierung",
  "city": "Unterföhring",
  "sourceCount": 2,
  "platforms": {
    "provenexpert": {
      "rating": 4.63,
      "reviewCount": 776,
      "lifetimeReviewCount": 809,
      "verifiedReviewCount": null,
      "recommendationRate": 99,
      "verificationPolicy": "source_declared"
    },
    "google_maps": {
      "rating": 5,
      "reviewCount": 5,
      "verificationPolicy": "unverified_public_reviews"
    }
  },
  "crossChannel": {
    "averageRating": 4.82,
    "ratingRange": 0.37,
    "totalRatingReviewCount": 781
  },
  "trustScore": 80.7,
  "trustScoreVersion": "dach-trust-v1",
  "benchmark": {
    "status": "ready",
    "basis": "category",
    "category": "Seminare",
    "cohortSize": 25,
    "trustScorePercentile": 87,
    "ratingPercentile": 79,
    "reviewVolumePercentile": 92
  },
  "matchConfidence": 1,
  "matchSignals": ["explicit_business_group"],
  "scrapedAt": "2026-07-26T11:00:00.000Z"
}
````

#### 2. Change row

```json
{
  "type": "change",
  "entityKey": "business_673e011f616ad6f1f205",
  "companyName": "S&P Unternehmerforum GmbH",
  "changeStatus": "changed",
  "previousScrapedAt": "2026-07-19T11:00:00.000Z",
  "trustScore": 80.7,
  "previousTrustScore": 79.9,
  "trustScoreDelta": 0.8,
  "totalReviewCountDelta": 12,
  "platformChanges": {
    "provenexpert": {
      "status": "present",
      "rating": 4.63,
      "previousRating": 4.61,
      "ratingDelta": 0.02,
      "reviewCount": 776,
      "previousReviewCount": 764,
      "reviewCountDelta": 12
    }
  },
  "scrapedAt": "2026-07-26T11:00:00.000Z"
}
```

#### 3. Platform profile row

Every source produces a normalized `profile` row. Platform-specific fields remain available, including ProvenExpert external sources, Trusted Shops star distribution and certificate status, eKomi sentiment percentages, and Google Maps coordinates.

The normalized count fields are:

- `ratingReviewCount`: number of reviews used by the platform's displayed rating period.
- `lifetimeReviewCount`: visible all-time count when the platform exposes it.
- `verifiedReviewCount`: count explicitly declared verified by that source; `null` means the Actor refuses to infer a count.
- `verificationPolicy`: explains how the source describes verification.

#### 4. Review row

ProvenExpert, Trusted Shops, and eKomi produce individual `review` rows with:

- Review ID, rating, text, subject, reviewer display name, and publication date.
- Recommendation state where derivable.
- Source verification status.
- eKomi order/experience date and business reply.
- ProvenExpert detailed subratings.

#### 5. Error row

Invalid or blocked profiles produce transparent, uncharged `error` rows without stopping valid inputs.

Business and change rows include `snapshotStatus`. A value of `complete` means every grouped source required for comparison succeeded. A value of `incomplete` includes `failedPlatforms`; its deltas and benchmark percentiles are intentionally suppressed.

### Input examples

#### One ProvenExpert profile with automatic Google matching

```json
{
  "startUrls": [
    {
      "url": "https://www.provenexpert.com/de-de/sp-unternehmerforum-gmbh/"
    }
  ],
  "followExternalProfiles": true,
  "maxReviewsPerProfile": 100
}
```

#### Guaranteed matching across four channels

Use a stable `id` when you already know the URLs. This bypasses fuzzy matching and guarantees that all URLs become one business row.

```json
{
  "businesses": [
    {
      "id": "customer-123",
      "companyName": "Example GmbH",
      "category": "Online-Marketing",
      "city": "Berlin",
      "provenExpertUrl": "https://www.provenexpert.com/de-de/example-gmbh/",
      "trustedShopsUrl": "https://www.trustedshops.de/bewertung/example-de",
      "eKomiUrl": "https://www.ekomi.de/cert/PARTNER_ID",
      "googleMapsUrl": "https://www.google.de/maps/place/Example+GmbH/..."
    }
  ],
  "maxReviewsPerProfile": 50
}
```

#### Discover and benchmark a sector

```json
{
  "searchQueries": [
    {
      "term": "Online-Marketing",
      "location": "Berlin",
      "maxProfiles": 100
    }
  ],
  "outputMode": "profiles_only",
  "maxReviewsPerProfile": 0,
  "followExternalProfiles": false,
  "minimumBenchmarkCohortSize": 10
}
```

#### Scheduled change monitor

Run this input daily or weekly with an Apify Schedule:

```json
{
  "businesses": [
    {
      "id": "competitor-a",
      "provenExpertUrl": "https://www.provenexpert.com/de-de/example/",
      "googleMapsUrl": "https://www.google.de/maps/place/Example/..."
    }
  ],
  "outputMode": "profiles_only",
  "maxReviewsPerProfile": 0,
  "saveHistory": true,
  "historyDatasetName": "competitor-reputation-history",
  "emitChanges": true,
  "changesOnly": true
}
```

The first run creates a `new` change. Later unchanged runs return no paid result rows when `changesOnly` is enabled. A new review, review-count movement, channel addition/removal, rating change above the configured threshold, or Trust Score movement produces output.

### Input reference

| Field | Default | Description |
|---|---:|---|
| `startUrls` | Sample ProvenExpert URL | Mixed supported profile URLs |
| `profileSlugs` | `[]` | ProvenExpert slugs |
| `businesses` | `[]` | Explicit cross-platform company groups |
| `searchQueries` | `[]` | ProvenExpert discovery queries; maximum 100 profiles per query |
| `locale` | `de-de` | Locale used for ProvenExpert URL construction |
| `outputMode` | `profile_and_reviews` | Controls raw profile/review rows |
| `maxReviewsPerProfile` | `20` | Maximum reviews per supported review source; hard maximum 500 |
| `sortBy` | `newest` | Newest, oldest, best, worst, or experiences first |
| `followExternalProfiles` | `true` | Directly refresh supported links found on ProvenExpert |
| `discoverExternalProfilesFromWebsite` | `true` | Check the company homepage for supported review badge/profile links |
| `includeBusinessSummary` | `true` | Emit matched cross-platform business rows |
| `emitChanges` | `true` | Emit comparison rows |
| `changesOnly` | `false` | Suppress unchanged results and known review IDs |
| `saveHistory` | `true` | Save snapshots plus indexed latest state for future runs |
| `historyDatasetName` | `dach-reputation-history` | Persistent time-series dataset; its latest-state KVS is derived automatically |
| `previousDatasetId` | Empty | Explicit comparison baseline selected with a read-only dataset picker |
| `benchmarkDatasetId` | Empty | Optional reference corpus selected with a read-only dataset picker |
| `minimumBenchmarkCohortSize` | `3` | Minimum sample before benchmark is ready |
| `ratingChangeThreshold` | `0.01` | Minimum rating movement treated as changed |
| `maxConcurrency` | `3` | Concurrent profile pages |
| `proxyConfiguration` | Direct | Optional Apify Proxy configuration |

### Trust Score methodology

`dach-trust-v1` is a transparent 0–100 composite:

| Component | Weight | Calculation |
|---|---:|---|
| Rating quality | 55% | Cross-channel rating normalized from 1–5 to 0–100 |
| Review volume | 20% | Log-scaled review count; large profiles cannot dominate linearly |
| Channel coverage | 10% | Coverage reaches 100 at three matched sources |
| Review freshness | 10% | Exponential decay from the newest observed review date |
| Verified-source share | 5% | Share of sources with transaction/post-transaction verification policies |

Cross-channel rating uses square-root review-count weights. This respects evidence volume without allowing a single very large channel to erase the others. The output contains every component and a version string, so downstream users can audit or replace the score.

### Benchmark methodology

Benchmarks use only data actually observed in the current input, a discovery query, or `benchmarkDatasetId`. The Actor never claims a global DACH percentile from an unobserved corpus.

- Exact normalized category cohorts are preferred.
- If the category cohort is too small, the supplied all-business cohort is used.
- `status: "insufficient_sample"` is returned below `minimumBenchmarkCohortSize`.
- Percentiles use a midpoint rank for ties.

For a market-wide benchmark, first run a sufficiently large discovery input and reuse its dataset ID as `benchmarkDatasetId`.

The benchmark is an observed-cohort percentile, not a claim about every DACH business. The Trust Score is a versioned analytical heuristic rather than a certification or financial/credit rating.

Incomplete multi-platform snapshots are excluded from benchmark percentiles and stored history. This prevents a temporary source outage from lowering a company's score or generating a false channel-removal alert.

### Entity matching

Profiles are linked using a scored combination of:

1. Explicit `businesses[].id`.
2. Exact website domain.
3. Normalized phone number.
4. Normalized company-name similarity.
5. Postal code or city.

The resulting `matchConfidence` and `matchSignals` make every automatic match inspectable. Use explicit groups for branches, franchises, or names that are intentionally different across platforms.

Automatic clusters cannot contain two profiles from the same platform unless the user explicitly placed them in the same `businesses[].id` group. This prevents transitive fuzzy matches from collapsing separate branches.

### Supported URL formats

- ProvenExpert localized and non-localized public profile URLs.
- Trusted Shops legacy `info_*.html` and modern `/bewertung/{shop-slug}` URLs.
- eKomi legacy `/bewertungen-*.html` and modern `/cert/{partnerId}` URLs.
- Public Google Maps place and short-share URLs. Google Maps produces aggregate fields only.

### API

#### JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('kamerozkan/provenexpert-reviews-scraper').call({
  searchQueries: [
    { term: 'Online-Marketing', location: 'Berlin', maxProfiles: 50 }
  ],
  outputMode: 'profiles_only',
  maxReviewsPerProfile: 0
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("kamerozkan/provenexpert-reviews-scraper").call(run_input={
    "startUrls": [
        {"url": "https://www.provenexpert.com/de-de/sp-unternehmerforum-gmbh/"}
    ],
    "followExternalProfiles": True,
    "maxReviewsPerProfile": 100,
})

items = client.dataset(run["defaultDatasetId"]).list_items().items
print(items)
```

### Pay-per-event pricing

The Actor is configured with these launch events:

| Event | Suggested launch price |
|---|---:|
| `business-result` | $0.04 per matched business row |
| `change-result` | $0.01 per change row |
| `profile-result` | $0.015 per platform profile |
| `review-result` | $0.001 per review |
| Synthetic `apify-actor-start` | $0.005 per GB of configured memory, minimum one event |

The synthetic `apify-default-dataset-item` event is intentionally omitted to prevent double charging. Error rows are not attached to a paid event. Higher Apify subscription tiers receive progressively lower event prices.

For launch, keep all custom prices visible and simple. After real Store usage appears, optimize around the highest-retention workflow—usually scheduled `changesOnly` monitoring or sector discovery.

### Reliability

- Browser-backed ProvenExpert pagination.
- ProvenExpert discovery uses its public search API and validates that the requested cohort was fully collected; incomplete discovery fails visibly instead of returning a silent ten-row subset.
- Trusted Shops review API pagination with explicit date/rating sorting.
- eKomi AJAX pagination.
- Modern and legacy Trusted Shops/eKomi URL support, including redirect-safe eKomi pagination.
- Direct Google Maps data with structured-metadata selectors and a clearly labeled ProvenExpert aggregate fallback when Google blocks a linked refresh.
- Duplicate review IDs removed per profile.
- Indexed latest state plus append-only time-series history; comparisons do not scan the full history.
- History advances only after all paid output is delivered. If the maximum run charge is reached, an uncharged `MAX_TOTAL_CHARGE_REACHED` row is emitted and the next run can safely retry.
- Partial source failures create an `incomplete` snapshot with unknown channel status; they never create false removed/added oscillations and never overwrite the last complete snapshot.
- Invalid profiles do not stop the remaining batch.
- A run with profile targets fails when every target fails, while legitimate zero-result discovery remains a successful empty result.
- Company-homepage discovery blocks localhost, private/link-local IPs, private DNS answers, and redirects to non-public network destinations.
- Images, media, and fonts are blocked to lower compute cost.
- Every image build must pass unit coverage for parsers, matching, scoring, benchmarks, deltas, delivery/history safety, URLs, DNS/SSRF checks, and discovery before the Actor can start.
- Live-tested multi-source crawling, second-run history comparisons, changes-only suppression, sector discovery, and 25-review external pagination.

### Legal and privacy

This Actor extracts data displayed on public profile pages. You are responsible for complying with platform terms, database rights, copyright, and applicable privacy laws such as GDPR. Avoid redistributing reviewer personal data without a valid purpose and legal basis.

This is an unofficial Actor. It is independent and is not affiliated with, endorsed by, or sponsored by ProvenExpert, Expert Systems, Trusted Shops, eKomi, or Google.

# Actor input Schema

## `startUrls` (type: `array`):

ProvenExpert, Trusted Shops, eKomi, or Google Maps business profile URLs.

## `profileSlugs` (type: `array`):

ProvenExpert slugs such as provenexpert-com.

## `businesses` (type: `array`):

Optional explicit company groups. URLs in the same object are guaranteed to be matched into one business row.

## `searchQueries` (type: `array`):

Discover public ProvenExpert profiles by sector/keyword and optional location. Results become the benchmark cohort.

## `locale` (type: `string`):

Locale used for slugs and non-localized ProvenExpert URLs.

## `outputMode` (type: `string`):

Business and change rows are controlled separately below. This option controls raw profile/review rows.

## `maxReviewsPerProfile` (type: `integer`):

Maximum native reviews saved per ProvenExpert, Trusted Shops, or eKomi profile. Google Maps currently returns aggregate reputation fields.

## `sortBy` (type: `string`):

Order used when the source supports sorting.

## `followExternalProfiles` (type: `boolean`):

Open supported Trusted Shops, eKomi, and Google Maps links found on ProvenExpert and refresh their aggregate data directly.

## `discoverExternalProfilesFromWebsite` (type: `boolean`):

Visit only the company homepage and follow supported ProvenExpert, Trusted Shops, eKomi, or Google Maps profile links found in anchors and badge iframes.

## `includeBusinessSummary` (type: `boolean`):

Match profiles and emit one business row with all channels and the DACH Trust Score.

## `emitChanges` (type: `boolean`):

Compare each business with its latest stored or supplied snapshot.

## `changesOnly` (type: `boolean`):

Suppress unchanged business/profile rows and reviews already present in the previous snapshot.

## `saveHistory` (type: `boolean`):

Append compact time-series snapshots and maintain an indexed latest-state store for fast future comparisons.

## `historyDatasetName` (type: `string`):

Persistent named dataset used for automatic time-series comparisons.

## `previousDatasetId` (type: `string`):

Optional explicit baseline. When empty, the named history dataset is used.

## `benchmarkDatasetId` (type: `string`):

Optional dataset containing business, business\_snapshot, or profile rows to enlarge the benchmark cohort.

## `minimumBenchmarkCohortSize` (type: `integer`):

Minimum comparable businesses required before a benchmark is marked ready.

## `ratingChangeThreshold` (type: `number`):

Minimum absolute rating movement counted as a change. Review count changes always count.

## `maxConcurrency` (type: `integer`):

Profiles processed in parallel. Keep this moderate for stable crawling.

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

Optional Apify Proxy configuration. Direct connections are used by default; enable proxy rotation if Google or another source blocks your cloud region.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.provenexpert.com/de-de/sp-unternehmerforum-gmbh/"
    }
  ],
  "profileSlugs": [],
  "businesses": [],
  "searchQueries": [],
  "locale": "de-de",
  "outputMode": "profile_and_reviews",
  "maxReviewsPerProfile": 20,
  "sortBy": "newest",
  "followExternalProfiles": true,
  "discoverExternalProfilesFromWebsite": true,
  "includeBusinessSummary": true,
  "emitChanges": true,
  "changesOnly": false,
  "saveHistory": true,
  "historyDatasetName": "dach-reputation-history",
  "minimumBenchmarkCohortSize": 3,
  "ratingChangeThreshold": 0.01,
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Business, change, profile, review, and error rows written to the default dataset.

# 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 = {
    "startUrls": [
        {
            "url": "https://www.provenexpert.com/de-de/sp-unternehmerforum-gmbh/"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("kamerozkan/provenexpert-reviews-scraper").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 = { "startUrls": [{ "url": "https://www.provenexpert.com/de-de/sp-unternehmerforum-gmbh/" }] }

# Run the Actor and wait for it to finish
run = client.actor("kamerozkan/provenexpert-reviews-scraper").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 '{
  "startUrls": [
    {
      "url": "https://www.provenexpert.com/de-de/sp-unternehmerforum-gmbh/"
    }
  ]
}' |
apify call kamerozkan/provenexpert-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=kamerozkan/provenexpert-reviews-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "ProvenExpert Reviews & DACH Reputation Monitor",
        "description": "Unofficial scraper for public ProvenExpert, Trusted Shops, eKomi, and Google Maps reputation data. Match businesses, monitor changes, and benchmark DACH trust signals.",
        "version": "0.3",
        "x-build-id": "8G4cglkPOuPPo4qXK"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/kamerozkan~provenexpert-reviews-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-kamerozkan-provenexpert-reviews-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/kamerozkan~provenexpert-reviews-scraper/runs": {
            "post": {
                "operationId": "runs-sync-kamerozkan-provenexpert-reviews-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/kamerozkan~provenexpert-reviews-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-kamerozkan-provenexpert-reviews-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": {
                    "startUrls": {
                        "title": "Review profile URLs",
                        "maxItems": 100,
                        "type": "array",
                        "description": "ProvenExpert, Trusted Shops, eKomi, or Google Maps business profile URLs.",
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "profileSlugs": {
                        "title": "ProvenExpert profile slugs",
                        "maxItems": 100,
                        "type": "array",
                        "description": "ProvenExpert slugs such as provenexpert-com.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "businesses": {
                        "title": "Cross-platform businesses",
                        "maxItems": 25,
                        "type": "array",
                        "description": "Optional explicit company groups. URLs in the same object are guaranteed to be matched into one business row.",
                        "items": {
                            "type": "object",
                            "properties": {
                                "id": {
                                    "type": "string",
                                    "title": "Stable business ID",
                                    "description": "Your optional stable identifier for this business."
                                },
                                "companyName": {
                                    "type": "string",
                                    "title": "Company name",
                                    "description": "Preferred company name used in the matched business row."
                                },
                                "category": {
                                    "type": "string",
                                    "title": "Benchmark category",
                                    "description": "Sector label used to select comparable businesses."
                                },
                                "city": {
                                    "type": "string",
                                    "title": "City",
                                    "description": "Optional city label for this business."
                                },
                                "provenExpertUrl": {
                                    "type": "string",
                                    "title": "ProvenExpert URL",
                                    "description": "Public ProvenExpert business profile URL."
                                },
                                "trustedShopsUrl": {
                                    "type": "string",
                                    "title": "Trusted Shops URL",
                                    "description": "Public Trusted Shops business profile URL."
                                },
                                "eKomiUrl": {
                                    "type": "string",
                                    "title": "eKomi URL",
                                    "description": "Public eKomi certificate/profile URL."
                                },
                                "googleMapsUrl": {
                                    "type": "string",
                                    "title": "Google Maps URL",
                                    "description": "Public Google Maps place URL."
                                }
                            }
                        },
                        "default": []
                    },
                    "searchQueries": {
                        "title": "ProvenExpert company discovery",
                        "maxItems": 5,
                        "type": "array",
                        "description": "Discover public ProvenExpert profiles by sector/keyword and optional location. Results become the benchmark cohort.",
                        "items": {
                            "type": "object",
                            "required": [
                                "term"
                            ],
                            "properties": {
                                "term": {
                                    "type": "string",
                                    "title": "Sector or keyword",
                                    "description": "The service, sector, or keyword to search on ProvenExpert."
                                },
                                "location": {
                                    "type": "string",
                                    "title": "Location",
                                    "description": "Optional city or region for the ProvenExpert search."
                                },
                                "maxProfiles": {
                                    "type": "integer",
                                    "title": "Maximum profiles",
                                    "description": "Maximum discovered profiles to process for this query.",
                                    "default": 50,
                                    "minimum": 1,
                                    "maximum": 100
                                }
                            }
                        },
                        "default": []
                    },
                    "locale": {
                        "title": "ProvenExpert locale",
                        "enum": [
                            "de-de",
                            "en-us",
                            "en-gb"
                        ],
                        "type": "string",
                        "description": "Locale used for slugs and non-localized ProvenExpert URLs.",
                        "default": "de-de"
                    },
                    "outputMode": {
                        "title": "Raw output mode",
                        "enum": [
                            "profile_and_reviews",
                            "profiles_only",
                            "reviews_only"
                        ],
                        "type": "string",
                        "description": "Business and change rows are controlled separately below. This option controls raw profile/review rows.",
                        "default": "profile_and_reviews"
                    },
                    "maxReviewsPerProfile": {
                        "title": "Maximum reviews per profile",
                        "minimum": 0,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Maximum native reviews saved per ProvenExpert, Trusted Shops, or eKomi profile. Google Maps currently returns aggregate reputation fields.",
                        "default": 20
                    },
                    "sortBy": {
                        "title": "Review sorting",
                        "enum": [
                            "newest",
                            "oldest",
                            "best",
                            "worst",
                            "experiences_first"
                        ],
                        "type": "string",
                        "description": "Order used when the source supports sorting.",
                        "default": "newest"
                    },
                    "followExternalProfiles": {
                        "title": "Follow linked external profiles",
                        "type": "boolean",
                        "description": "Open supported Trusted Shops, eKomi, and Google Maps links found on ProvenExpert and refresh their aggregate data directly.",
                        "default": true
                    },
                    "discoverExternalProfilesFromWebsite": {
                        "title": "Discover review badges on company websites",
                        "type": "boolean",
                        "description": "Visit only the company homepage and follow supported ProvenExpert, Trusted Shops, eKomi, or Google Maps profile links found in anchors and badge iframes.",
                        "default": true
                    },
                    "includeBusinessSummary": {
                        "title": "Create cross-platform business rows",
                        "type": "boolean",
                        "description": "Match profiles and emit one business row with all channels and the DACH Trust Score.",
                        "default": true
                    },
                    "emitChanges": {
                        "title": "Create change rows",
                        "type": "boolean",
                        "description": "Compare each business with its latest stored or supplied snapshot.",
                        "default": true
                    },
                    "changesOnly": {
                        "title": "Output changes only",
                        "type": "boolean",
                        "description": "Suppress unchanged business/profile rows and reviews already present in the previous snapshot.",
                        "default": false
                    },
                    "saveHistory": {
                        "title": "Save time-series snapshots",
                        "type": "boolean",
                        "description": "Append compact time-series snapshots and maintain an indexed latest-state store for fast future comparisons.",
                        "default": true
                    },
                    "historyDatasetName": {
                        "title": "History dataset name",
                        "minLength": 1,
                        "maxLength": 63,
                        "type": "string",
                        "description": "Persistent named dataset used for automatic time-series comparisons.",
                        "default": "dach-reputation-history"
                    },
                    "previousDatasetId": {
                        "title": "Previous snapshot dataset ID or name",
                        "type": "string",
                        "description": "Optional explicit baseline. When empty, the named history dataset is used."
                    },
                    "benchmarkDatasetId": {
                        "title": "Benchmark dataset ID or name",
                        "type": "string",
                        "description": "Optional dataset containing business, business_snapshot, or profile rows to enlarge the benchmark cohort."
                    },
                    "minimumBenchmarkCohortSize": {
                        "title": "Minimum benchmark cohort",
                        "minimum": 2,
                        "maximum": 1000,
                        "type": "integer",
                        "description": "Minimum comparable businesses required before a benchmark is marked ready.",
                        "default": 3
                    },
                    "ratingChangeThreshold": {
                        "title": "Rating change threshold",
                        "minimum": 0,
                        "maximum": 1,
                        "type": "number",
                        "description": "Minimum absolute rating movement counted as a change. Review count changes always count.",
                        "default": 0.01
                    },
                    "maxConcurrency": {
                        "title": "Maximum concurrency",
                        "minimum": 1,
                        "maximum": 6,
                        "type": "integer",
                        "description": "Profiles processed in parallel. Keep this moderate for stable crawling.",
                        "default": 3
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Optional Apify Proxy configuration. Direct connections are used by default; enable proxy rotation if Google or another source blocks your cloud region.",
                        "default": {
                            "useApifyProxy": 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
                                    }
                                }
                            },
                            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
