# Ace Hardware Product Reviews Scraper (`automation-lab/ace-hardware-product-reviews-scraper`) Actor

Extract public Ace Hardware reviews with ratings, text, authors, dates, recommendation, helpfulness, media, syndication, and product statistics. Export JSON, CSV, or Excel; schedule recurring monitoring. No login required.

- **URL**: https://apify.com/automation-lab/ace-hardware-product-reviews-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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 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/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

Extract public **Ace Hardware product reviews** into clean JSON, CSV, Excel, XML, or RSS records.

Use an Ace product URL or item ID to collect review text, ratings, authors, dates, recommendation signals, helpfulness, media, syndication, and product-level rating statistics.

No Ace login, private API key, or browser automation is required.

### What does Ace Hardware Product Reviews Scraper do?

Ace Hardware Product Reviews Scraper turns public customer feedback from [Ace Hardware](https://www.acehardware.com/) product pages into analysis-ready records.

It can:

- 🔗 Accept full Ace product URLs or numeric item IDs.
- 📄 Paginate through every available public review.
- 🎯 Filter by stars, recommendation, and submission date.
- ↕️ Sort by date, rating, or helpfulness.
- 🖼️ Capture review photos, videos, badges, and merchant responses.
- 📊 Add product metadata and aggregate rating distributions.
- 🕐 Support scheduled incremental monitoring with date filters.

The Actor uses Ace's public structured review feed rather than a heavy browser, which keeps runs fast and predictable.

### Who is it for? Ace review monitoring teams

**Brands and Ace vendors**

- Monitor feedback on products sold through Ace.
- Find recurring defects and packaging complaints.
- Track recommendation rates after a product update.

**Product-quality teams**

- Review one- and two-star comments in a shared spreadsheet.
- Compare rating distributions across item IDs.
- Route new negative feedback into an issue tracker.

**Retail and ecommerce analysts**

- Build recurring product-review datasets.
- Compare public sentiment across product lines.
- Preserve timestamped review snapshots for trend analysis.

**Agencies and data teams**

- Export normalized Ace reviews for clients.
- Feed review text into sentiment or topic models.
- Automate collection through the API, schedules, or webhooks.

### Why use this Ace Hardware review extractor?

- ✅ **No login required** — collect public reviews without an Ace account.
- ✅ **HTTP-first extraction** — no browser overhead for the core workflow.
- ✅ **One row per review** — easy to filter, join, deduplicate, and export.
- ✅ **Product context included** — name, brand, image, MPN, UPC, and aggregate statistics.
- ✅ **Monitoring filters** — pull only reviews submitted in a chosen period.
- ✅ **Failure isolation** — one unavailable item does not discard successful products.
- ✅ **Apify integrations** — use schedules, API calls, webhooks, Make, Zapier, and cloud storage.

### What Ace Hardware review data can you extract?

| Category | Fields |
|---|---|
| Product identity | Product ID, name, brand, URL, image, category |
| Product identifiers | Manufacturer part numbers and UPCs |
| Product summary | Average rating, total reviews, recommended/not-recommended counts |
| Rating distribution | Counts for one through five stars |
| Review content | Review ID, title, full text, rating, rating range |
| Reviewer | Nickname, author ID, location, locale |
| Timing | Submission time, last modification time, scrape time |
| Signals | Recommended, rating-only, featured, syndicated |
| Engagement | Helpful, unhelpful, inappropriate, and comment counts |
| Rich content | Badges, context, secondary ratings, photos, videos |
| Responses | Merchant responses and syndication source |

Optional source fields are omitted when Ace does not provide them; numeric counters remain numbers and booleans remain booleans.

### How much does it cost to scrape Ace Hardware reviews?

This Actor uses **pay-per-event** pricing: a small run-start charge plus one charge per review saved.

| Plan tier | Current price per review |
|---|---:|
| Free | $0.000039795 |
| Starter / Bronze | $0.000034605 |
| Scale / Silver | $0.000026992 |
| Business / Gold | $0.000020763 |
| Platinum | $0.000013842 |
| Diamond | $0.000010000 |

A run also has a $0.005 start event.

Example at the Free tier:

- 10 reviews: about $0.0054.
- 100 reviews: about $0.0090.
- 1,000 reviews: about $0.0448.

Final cost depends on the number of matching reviews emitted, not the number of source pages checked.

### How to scrape Ace Hardware product reviews

1. Open Ace Hardware Product Reviews Scraper on Apify.
2. Paste one or more Ace product URLs into **Product URLs**.
3. Alternatively, enter numeric values under **Item IDs**.
4. Set the maximum reviews per product.
5. Optionally choose rating, recommendation, and date filters.
6. Click **Start**.
7. Preview records in the Dataset tab.
8. Export the dataset as JSON, CSV, Excel, XML, or RSS.

Start with the prefilled Bosch drill URL to verify the workflow quickly.

### Input parameters

| Parameter | Type | Default | Purpose |
|---|---|---|---|
| `productUrls` | string array | sample URL in prefill | Ace Hardware product page URLs |
| `productIds` | string array | `[]` | Numeric Ace item IDs |
| `maxReviewsPerProduct` | integer | `100` | Maximum matching rows per product |
| `sort` | string | `newest` | Date, rating, or helpfulness order |
| `ratings` | string array | `[]` | Selected ratings from 1 to 5 |
| `recommended` | string | `all` | All, recommended, or not recommended |
| `submittedAfter` | string | empty | Inclusive ISO date lower bound |
| `submittedBefore` | string | empty | Inclusive ISO date upper bound |
| `includeRatingsOnly` | boolean | `true` | Keep reviews without written text |
| `maxRequestRetries` | integer | `3` | Bounded retries for temporary errors |

Provide at least one valid Ace URL or item ID.

Invalid dates and invalid rating values fail closed instead of silently widening the query.

### Input examples

Collect the 100 newest reviews:

```json
{
  "productIds": ["2398303"],
  "maxReviewsPerProduct": 100,
  "sort": "newest"
}
````

Collect negative reviews from a product URL:

```json
{
  "productUrls": [
    "https://www.acehardware.com/departments/tools/power-tools/corded-drills/2398303"
  ],
  "ratings": ["1", "2"],
  "recommended": "notRecommended",
  "maxReviewsPerProduct": 250
}
```

Monitor feedback submitted during 2026:

```json
{
  "productIds": ["2398303"],
  "submittedAfter": "2026-01-01",
  "submittedBefore": "2026-12-31",
  "sort": "newest"
}
```

### Output example

Each row represents one review:

```json
{
  "productId": "2398303",
  "productName": "Bosch 7 amps 1/2 in. Corded Hammer Drill",
  "productBrand": "Bosch",
  "productUrl": "https://www.acehardware.com/p/2398303",
  "averageRating": 3.2972972972972974,
  "totalReviewCount": 74,
  "rating1Count": 22,
  "rating5Count": 32,
  "reviewId": "300170121",
  "rating": 1,
  "ratingRange": 5,
  "reviewTitle": "Fails to perform its base task.",
  "nickname": "Ashlela",
  "submissionTime": "2026-04-18T17:58:10.000+00:00",
  "isRecommended": false,
  "helpfulVotes": 0,
  "unhelpfulVotes": 0,
  "photoUrls": ["https://photos-us.bazaarvoice.com/photo/example"],
  "isSyndicated": true,
  "syndicationSource": "boschtools.com",
  "contentLocale": "en_US",
  "scrapedAt": "2026-07-16T00:00:00.000Z"
}
```

Exact optional fields vary because reviewers do not always add text, location, media, or recommendation status.

### Tips for reliable Ace review extraction

- Start with one item and a low limit before submitting a large product list.
- Use item IDs when you already have a catalog export; they avoid URL formatting issues.
- Use `sort: newest` with `submittedAfter` for recurring monitoring.
- Remember that the maximum applies to **matching** reviews after filters.
- Use one- and two-star filters to build a product-quality alert stream.
- Deduplicate historical exports by `reviewId`.
- Schedule runs at a cadence appropriate for each product's review volume.
- Keep rating-only records when calculating rating distributions.

### Scheduling review monitoring

Apify schedules can run this Actor hourly, daily, weekly, or on a custom cron expression.

A practical workflow is:

1. Store tracked item IDs in task input.
2. Set `sort` to `newest`.
3. Set `submittedAfter` to the start of your monitoring window.
4. Run the task daily or weekly.
5. Deduplicate rows downstream by `reviewId`.
6. Trigger alerts for low ratings or `isRecommended: false`.

For a rolling integration, update the date input through the API before each run.

### Integrations

**Ace reviews → Google Sheets**

Append newly submitted reviews to a quality dashboard and build pivot tables by product, star rating, or recommendation.

**Ace reviews → Slack or Discord**

Send alerts whenever a scheduled run returns a one-star review or a not-recommended product experience.

**Ace reviews → Make or Zapier**

Route records to Airtable, Notion, HubSpot, or an issue tracker without writing code.

**Ace reviews → data warehouse**

Use a webhook after each run, fetch the default dataset, and load rows into BigQuery, Snowflake, or PostgreSQL.

**Ace reviews → AI analysis**

Send `reviewText` into a topic, sentiment, complaint-classification, or product-defect workflow.

### API usage with the Apify API

Node.js with `apify-client`:

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/ace-hardware-product-reviews-scraper').call({
  productIds: ['2398303'],
  maxReviewsPerProduct: 100,
  sort: 'newest'
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

Python with `apify-client`:

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/ace-hardware-product-reviews-scraper').call(run_input={
    'productIds': ['2398303'],
    'maxReviewsPerProduct': 100,
    'sort': 'newest',
})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

cURL:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~ace-hardware-product-reviews-scraper/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"productIds":["2398303"],"maxReviewsPerProduct":100,"sort":"newest"}'
```

### Use with AI agents via MCP

This Actor can be used by AI assistants through Apify's [Model Context Protocol integration](https://docs.apify.com/platform/integrations/mcp).

Claude Code:

```bash
claude mcp add --transport http apify "https://mcp.apify.com?tools=automation-lab/ace-hardware-product-reviews-scraper"
```

Claude Desktop, Cursor, or VS Code MCP configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/ace-hardware-product-reviews-scraper"
    }
  }
}
```

Example prompts:

- “Use `automation-lab/ace-hardware-product-reviews-scraper` to collect the newest 100 reviews for Ace item 2398303.”
- “Extract one- and two-star Ace reviews from these product URLs and summarize recurring product defects.”
- “Monitor not-recommended Ace Hardware reviews submitted since the start of this month.”

OAuth connects the MCP server to your Apify account on first use.

### Export formats and storage

The default dataset supports:

- JSON for applications and APIs.
- CSV or Excel for analysts and spreadsheet users.
- XML and RSS for compatible integration tools.
- JSONL for streaming and machine-learning pipelines.

Apify datasets can be retained, named, downloaded, or fetched through API endpoints.

The `RUN_SUMMARY` key-value-store record reports processed products, failed products, saved reviews, and completion time.

### Legality: is it legal to scrape Ace Hardware reviews?

This Actor extracts public product-review content that is visible without a login.

You are responsible for using the data lawfully and ethically, respecting applicable laws, Ace Hardware's terms, copyright, privacy rights, and data-protection obligations.

Avoid republishing personal data unnecessarily, do not use review data for harassment or discrimination, and retain only the fields needed for your legitimate purpose.

This documentation is not legal advice. Consult qualified counsel when your use case involves regulated decisions or personal-data processing.

### Troubleshooting

**Why did the run return no reviews?**

Confirm the item ID belongs to an Ace Hardware product and that public reviews exist. Also check whether rating, recommendation, or date filters exclude all source records.

**Why was a product URL skipped?**

Only `acehardware.com` product URLs with a numeric item ID are accepted. Search/category URLs and links from other domains are rejected to preserve product scope.

**Why are some optional fields absent?**

Ace reviewers do not always provide text, location, recommendation, media, context answers, or secondary ratings. Missing optional source values are omitted rather than invented.

**How fast is the scraper?**

The structured API retrieves up to 100 source reviews per request. Most single-product runs finish in seconds, with duration increasing for large product lists and deep histories.

### FAQ

**Can I scrape multiple Ace products in one run?**

Yes. Add multiple URLs, item IDs, or both. Duplicate item IDs are processed once.

**Can I fetch all reviews?**

Yes. Set `maxReviewsPerProduct` high enough for the product's review count, up to 5,000.

**Can I extract only negative reviews?**

Yes. Set `ratings` to `["1", "2"]`, and optionally set `recommended` to `notRecommended`.

**Does this use an official Ace API?**

It uses the public structured review service loaded by Ace product pages. It does not require a private Ace account or user-supplied API credential.

**How are duplicates handled?**

The Actor deduplicates emitted rows by the public `reviewId` during each run. Use the same field to deduplicate across scheduled runs.

**Can I use the free Apify plan?**

Yes. Small runs fit comfortably within typical free-platform credits; exact capacity depends on current Apify plan pricing and your other usage.

### Related ecommerce scrapers

Explore other `automation-lab` tools:

- [Walmart Reviews Scraper](https://apify.com/automation-lab/walmart-reviews-scraper)
- [Target Product Reviews Scraper](https://apify.com/automation-lab/target-product-reviews-scraper)
- [Lowe's Product Reviews Scraper](https://apify.com/automation-lab/lowes-product-reviews-scraper)
- [Best Buy Reviews Scraper](https://apify.com/automation-lab/best-buy-reviews-scraper)
- [PetSmart Product Reviews Scraper](https://apify.com/automation-lab/petsmart-product-reviews-scraper)
- [Ulta Product Reviews Scraper](https://apify.com/automation-lab/ulta-product-reviews-scraper)
- [Amazon Reviews Scraper](https://apify.com/automation-lab/amazon-reviews-scraper)

Use consistent identifiers and timestamps to combine these retailer-specific review datasets in a shared analytics pipeline.

### Data-quality notes

Ratings and counts come directly from the public Ace review service at run time.

Syndicated reviews may have an original source different from Ace; check `isSyndicated` and `syndicationSource` when attribution matters.

Aggregate rating statistics describe the complete product review set at scrape time, even when the run emits only a filtered subset.

The Actor never fabricates missing reviewer fields, recommendation values, or media URLs.

# Actor input Schema

## `productUrls` (type: `array`):

Add full Ace Hardware product page URLs. The numeric item ID is read from each URL.

## `productIds` (type: `array`):

Add numeric Ace Hardware item IDs, such as 2398303.

## `maxReviewsPerProduct` (type: `integer`):

Stop after saving this many matching reviews for each Ace product.

## `sort` (type: `string`):

Choose the order in which public reviews are collected.

## `ratings` (type: `array`):

Optionally keep selected star ratings. Leave empty to include ratings 1–5.

## `recommended` (type: `string`):

Keep all reviews, only recommended reviews, or only not-recommended reviews.

## `submittedAfter` (type: `string`):

Optional ISO date, for example 2026-01-01. Useful for incremental monitoring.

## `submittedBefore` (type: `string`):

Optional ISO date, for example 2026-12-31.

## `includeRatingsOnly` (type: `boolean`):

Keep reviews with a star rating but no written title or text.

## `maxRequestRetries` (type: `integer`):

Retry temporary 429 and server errors with exponential backoff.

## Actor input object example

```json
{
  "productUrls": [
    "https://www.acehardware.com/departments/tools/power-tools/corded-drills/2398303"
  ],
  "productIds": [],
  "maxReviewsPerProduct": 10,
  "sort": "newest",
  "ratings": [],
  "recommended": "all",
  "submittedAfter": "",
  "submittedBefore": "",
  "includeRatingsOnly": true,
  "maxRequestRetries": 3
}
```

# Actor output Schema

## `reviews` (type: `string`):

No description

## `runSummary` (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 = {
    "productUrls": [
        "https://www.acehardware.com/departments/tools/power-tools/corded-drills/2398303"
    ],
    "maxReviewsPerProduct": 10,
    "sort": "newest"
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/ace-hardware-product-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 = {
    "productUrls": ["https://www.acehardware.com/departments/tools/power-tools/corded-drills/2398303"],
    "maxReviewsPerProduct": 10,
    "sort": "newest",
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/ace-hardware-product-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 '{
  "productUrls": [
    "https://www.acehardware.com/departments/tools/power-tools/corded-drills/2398303"
  ],
  "maxReviewsPerProduct": 10,
  "sort": "newest"
}' |
apify call automation-lab/ace-hardware-product-reviews-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Ace Hardware Product Reviews Scraper",
        "description": "Extract public Ace Hardware reviews with ratings, text, authors, dates, recommendation, helpfulness, media, syndication, and product statistics. Export JSON, CSV, or Excel; schedule recurring monitoring. No login required.",
        "version": "0.1",
        "x-build-id": "mmdXrM2bvWw6nV8bc"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/automation-lab~ace-hardware-product-reviews-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-automation-lab-ace-hardware-product-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/automation-lab~ace-hardware-product-reviews-scraper/runs": {
            "post": {
                "operationId": "runs-sync-automation-lab-ace-hardware-product-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/automation-lab~ace-hardware-product-reviews-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-automation-lab-ace-hardware-product-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": {
                    "productUrls": {
                        "title": "Product URLs",
                        "type": "array",
                        "description": "Add full Ace Hardware product page URLs. The numeric item ID is read from each URL.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "productIds": {
                        "title": "Item IDs",
                        "type": "array",
                        "description": "Add numeric Ace Hardware item IDs, such as 2398303.",
                        "items": {
                            "type": "string"
                        },
                        "default": []
                    },
                    "maxReviewsPerProduct": {
                        "title": "Maximum reviews per product",
                        "minimum": 1,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Stop after saving this many matching reviews for each Ace product.",
                        "default": 100
                    },
                    "sort": {
                        "title": "Sort reviews",
                        "enum": [
                            "newest",
                            "oldest",
                            "highestRating",
                            "lowestRating",
                            "mostHelpful"
                        ],
                        "type": "string",
                        "description": "Choose the order in which public reviews are collected.",
                        "default": "newest"
                    },
                    "ratings": {
                        "title": "Star ratings",
                        "type": "array",
                        "description": "Optionally keep selected star ratings. Leave empty to include ratings 1–5.",
                        "items": {
                            "type": "string"
                        },
                        "default": []
                    },
                    "recommended": {
                        "title": "Recommendation filter",
                        "enum": [
                            "all",
                            "recommended",
                            "notRecommended"
                        ],
                        "type": "string",
                        "description": "Keep all reviews, only recommended reviews, or only not-recommended reviews.",
                        "default": "all"
                    },
                    "submittedAfter": {
                        "title": "Submitted on or after",
                        "type": "string",
                        "description": "Optional ISO date, for example 2026-01-01. Useful for incremental monitoring.",
                        "default": ""
                    },
                    "submittedBefore": {
                        "title": "Submitted on or before",
                        "type": "string",
                        "description": "Optional ISO date, for example 2026-12-31.",
                        "default": ""
                    },
                    "includeRatingsOnly": {
                        "title": "Include rating-only reviews",
                        "type": "boolean",
                        "description": "Keep reviews with a star rating but no written title or text.",
                        "default": true
                    },
                    "maxRequestRetries": {
                        "title": "Maximum request retries",
                        "minimum": 1,
                        "maximum": 6,
                        "type": "integer",
                        "description": "Retry temporary 429 and server errors with exponential backoff.",
                        "default": 3
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
