# Hermes Birkin/Kelly & Chanel Classic Cross-Platform Arbitrage (`kazkn/hermes-birkin-kelly-arbitrage`) Actor

Find resale spread candidates for Hermes Birkin/Kelly and Chanel Classic Flap across Vestiaire, Rebag, Fashionphile, and 1stDibs. Normalize condition, size, material, hardware, price, and estimated ROI for daily sourcing workflows.

- **URL**: https://apify.com/kazkn/hermes-birkin-kelly-arbitrage.md
- **Developed by:** [KazKN](https://apify.com/kazkn) (community)
- **Categories:** E-commerce, Automation, AI
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.10 / 1,000 normalized listings

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.md):

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

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

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

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

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

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

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

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

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


# README

## Hermes Birkin/Kelly + Chanel Classic Flap Arbitrage Scraper

Hermes Birkin/Kelly + Chanel Classic Flap Arbitrage is an Apify Actor for
comparing active Birkin, Kelly, and Chanel Classic Flap resale listings across
Vestiaire Collective, Rebag, Fashionphile, and 1stDibs. Use it as a luxury
handbag resale price monitor, sourcing scraper, strict buyer watchlist, or
API-driven market research tool.

The Actor finds public listings, normalizes bag attributes, groups comparable
items, and estimates whether a cross-platform spread still looks interesting
after fees, shipping, repair/authentication buffers, and FX/tax assumptions. It
separates strict arbitrage opportunities from review candidates, so you can see
useful spreads without pretending incomplete marketplace data is an exact comp.

[Run the Actor on Apify](https://apify.com/kazkn/hermes-birkin-kelly-arbitrage)
or connect it to Apify schedules, datasets, webhooks, API clients, Google
Sheets, Slack, Make, Zapier, or MCP-compatible workflows.

![Pink-haired voxel analyst comparing generic luxury handbag listings across resale marketplaces](https://api.apify.com/v2/key-value-stores/MEmF9KxfAJPom7iN6/records/arbitrage-hero.png)

### Quick Links

- Start here: [Quick Start](#quick-start), [Example Input](#example-input),
  [Input Fields Explained](#input-fields-explained), and
  [Output Records](#output-records).
- Deal logic: [Deal Thresholds](#4-deal-thresholds),
  [Why You Might See 0 Opportunities](#why-you-might-see-0-opportunities), and
  [FAQ / Common Questions](#faq--common-questions).
- Automation: [API Usage](#api-usage), [Cost And Performance Tips](#cost-and-performance-tips),
  [Apify API docs](https://docs.apify.com/api/v2),
  [Apify schedules](https://docs.apify.com/platform/schedules), and
  [Apify webhooks](https://docs.apify.com/platform/integrations/webhooks).
- Data export: [Apify dataset docs](https://docs.apify.com/platform/storage/dataset)
  for JSON, CSV, Excel, XML, HTML, and API output.
- Related KazKN resale tools:
  [Vinted Smart Scraper](https://apify.com/kazkn/vinted-smart-scraper) and
  [Vinted Turbo Scraper](https://apify.com/kazkn/vinted-turbo-scraper).

### Quick Start

Use these settings for your first run:

| Section                        | Recommended first value                 | Why                                                                      |
| ------------------------------ | --------------------------------------- | ------------------------------------------------------------------------ |
| Marketplaces                   | Vestiaire, Rebag, Fashionphile, 1stDibs | Compare all supported resale sources.                                    |
| Bag models                     | Birkin, Kelly, and Chanel Classic Flap  | Start broad before narrowing to a buyer brief.                           |
| Targeting mode                 | Broad scan                              | Finds market spread candidates without requiring exact target fields.    |
| Max listings per marketplace   | `60`                                    | Enough rows to inspect signals without a heavy first run.                |
| Max pages per marketplace      | `1`                                     | Keeps the first run fast and predictable.                                |
| Minimum price gap before costs | `12%`                                   | Filters tiny price differences before fees.                              |
| Minimum profit after costs     | `8%`                                    | Keeps only candidates that still look interesting after estimated costs. |

![First run guide showing Scan scope, scan limits, and output records](https://api.apify.com/v2/key-value-stores/MEmF9KxfAJPom7iN6/records/first-run-guide.png?v=20260616-native-text)

After the run, open the dataset in this order:

1. `run_summary` - check marketplace status and total counts.
2. `spread_candidate` - review useful cross-platform spreads that need human
   verification.
3. `arbitrage_opportunity` - strict comps that passed spread and ROI gates.
4. `listing_review` - normalized listing-level rows for spreadsheet review.
5. `unmatched_listing` - optional diagnostics when a listing lacked enough data
   for strict matching.

### What You Get In One Run

| Output               | What it answers                                                                |
| -------------------- | ------------------------------------------------------------------------------ |
| Normalized listings  | What Birkin/Kelly/Classic Flap inventory is live across the four marketplaces? |
| Strict opportunities | Which comparable bags pass price gap and estimated net ROI thresholds?         |
| Spread candidates    | Which relaxed comps look promising but need manual checks?                     |
| Watchlist candidates | Which listings match a known buyer target?                                     |
| Run summary          | Did each marketplace work, and how many rows did the Actor classify?           |
| Dataset views        | Which rows should I inspect first without filtering JSON manually?             |

Verified smoke run on build `0.0.18`: a broad 4-platform scan with `60` listings
per marketplace and `1` page per marketplace returned `167` listings, `8`
spread candidates, `0` platform errors, and `0` suspicious non-bag rows. Live
inventory changes every run, so treat this as a working-output example, not a
guarantee of future deal volume.

### Who This Actor Is For

| Good fit                                                                     | Not a good fit                                                    |
| ---------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| Luxury handbag resellers checking public asking prices.                      | Buyers expecting automatic authentication.                        |
| Sourcing teams building a daily Birkin/Kelly/Classic Flap shortlist.         | Users who need sold-comps or final transaction prices.            |
| Personal shoppers monitoring one strict buyer request.                       | Users who want the Actor to buy, reserve, or message sellers.     |
| Analysts exporting luxury handbag resale data to spreadsheets or dashboards. | Users who need legal, tax, investment, or resale business advice. |
| Developers who want a luxury handbag price comparison API on Apify.          | Users who need a generic Rolex/jewelry/luxury scraper.            |

### FAQ / Common Questions

| Question                               | Short answer                                                                                                                                                        |
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| What should I run first?               | Use [Broad scan](#quick-start), all 4 marketplaces, `60` listings, and `1` page.                                                                                    |
| Why do I see `0` strict opportunities? | Strict matching may be doing its job. Check [Why You Might See 0 Opportunities](#why-you-might-see-0-opportunities).                                                |
| Which dataset rows matter first?       | Start with `run_summary`, then `spread_candidate`, then `arbitrage_opportunity`.                                                                                    |
| Can I automate this?                   | Yes. Use [Apify schedules](https://docs.apify.com/platform/schedules), [webhooks](https://docs.apify.com/platform/integrations/webhooks), or the [API](#api-usage). |
| Can I export to CSV or Excel?          | Yes. Use Apify dataset exports or the [dataset API](https://docs.apify.com/platform/storage/dataset).                                                               |

For edge cases, fees, strict targeting, legality, and API details, see the
[Detailed FAQ](#detailed-faq).

### Important Disclaimer

It is not a profit guarantee, sold-comps database, authentication service,
financial advisor, or legal advisor. It is a strict screening tool for building a
cleaner shortlist before manual due diligence.

This Actor is independent and is not affiliated with, endorsed by, or sponsored
by Hermès, Chanel, Vestiaire Collective, Rebag, Fashionphile, or 1stDibs. Brand and
marketplace names are used only to describe public listing sources and products
being compared.

### What Does This Luxury Handbag Arbitrage Actor Do?

The Actor scrapes active public resale listings from four luxury marketplaces and
returns a structured dataset with:

- Normalized Hermes Birkin, Hermes Kelly, and Chanel Classic Flap listings.
- Model, size, color, material, hardware, condition, price, currency, image, and
  URL fields where available.
- Watchlist candidates for known target bags.
- Strict cross-platform match groups.
- Review candidates when model, size, color, and condition match but marketplace
  data is too incomplete for a strict deal.
- Gross price spread before costs.
- Estimated net ROI after user-controlled fees and cost buffers.
- Platform errors and run summaries so you can quickly see what worked.

In plain English: it replaces the first pass of manually checking several luxury
resale sites and copying comparable high-demand handbag listings into a
spreadsheet.

### Why Scrape Hermes And Chanel Resale Listings?

Hermes Birkin/Kelly and Chanel Classic Flap resale research is still mostly
manual: open several marketplaces, search each model, compare condition, size,
color, leather/material, hardware, seller fees, and then copy everything into a
spreadsheet. That breaks down fast when you monitor multiple bags or run daily
sourcing checks.

This Actor turns that workflow into a repeatable scan:

- Scrape active Birkin, Kelly, and Chanel Classic Flap listings from 4 resale
  marketplaces.
- Normalize model, size, color, material, hardware, condition, price, currency,
  seller/location hints, image URLs, and listing URL where available.
- Build strict match groups only when core attributes are comparable.
- Calculate gross price gap before costs.
- Estimate net ROI after sell-side fees, shipping, repair/authentication buffer,
  and FX/tax buffer.
- Return a dataset you can filter, export, schedule, or send into Google Sheets,
  Airtable, Slack, email, or your own pricing workflow.

### What It Is Best For

| Use case                          | How to use it                                                                                                                                       |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| Daily luxury handbag sourcing     | Run all 4 marketplaces every morning and review `spread_candidate`, `watchlist_candidate`, and `arbitrage_opportunity` rows.                        |
| Strict buyer watchlist monitoring | Switch `watchlistMode` to `strict_target` and enter a known target such as Birkin 25 black Togo GHW or Chanel Medium Classic Flap black caviar GHW. |
| Cross-platform price comparison   | Compare Vestiaire, Rebag, Fashionphile, and 1stDibs asking prices in one normalized dataset.                                                        |
| Reseller spreadsheet building     | Export `listing_review` rows with title, price, condition, URL, and match exclusion reasons.                                                        |
| Due diligence shortlist           | Use the Actor to find possible spreads, then manually verify authenticity, photos, seller terms, shipping, taxes, and liquidity.                    |
| Market research                   | Track which sizes, leathers, colors, and conditions appear most often across public resale inventory.                                               |

### Actor vs Manual Research

| Workflow            | What you get                                                                                                                     | Main weakness                                                   |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
| Manual spreadsheet  | Full human judgment on every listing.                                                                                            | Slow, hard to repeat, and easy to miss cross-platform spreads.  |
| Single-site scraper | Cleaner inventory from one marketplace.                                                                                          | No cross-platform price gap, no sell-route comparison.          |
| This Actor          | Four-platform Birkin/Kelly/Classic Flap scan, normalized attributes, spread candidates, strict opportunities, and ROI estimates. | Still requires manual due diligence before buying or reselling. |

### Marketplaces Covered

| Marketplace          | Best signal                                             | Notes                                                                                   |
| -------------------- | ------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| Vestiaire Collective | Broad international inventory and lower-price discovery | Uses public search data. Condition is normalized when exposed.                          |
| Rebag                | Structured resale listings and public asking prices     | Condition is enriched from listing detail pages when search cards omit it.              |
| Fashionphile         | US-focused pre-owned luxury inventory                   | Condition is enriched from detail pages. Accessory-only false positives are filtered.   |
| 1stDibs              | Rare, vintage, exotic, and dealer inventory             | Some listings expose fewer condition details, so strict matching may exclude more rows. |

### What Data Can You Get?

The dataset is designed for spreadsheet review, alerting, API workflows, and
manual due diligence.

| Data group       | Example fields                                                                                   |
| ---------------- | ------------------------------------------------------------------------------------------------ |
| Listing identity | `platform`, `platformListingId`, `title`, `url`, `sellerName`, `location`, `images`              |
| Bag attributes   | `model`, `size`, `colorRaw`, `colorBucket`, `materialRaw`, `hardwareBucket`, `conditionBucket`   |
| Pricing          | `price`, `currency`, `grossSpread`, `grossSpreadPercent`, `estimatedNetSellValue`                |
| ROI estimate     | `estimatedPlatformFee`, `estimatedPaymentFee`, `estimatedPlanCost`, `estimatedNetRoiPercent`     |
| Matching quality | `matchKey`, `matchEligibility`, `confidenceScore`, `matchExclusionReasons`, `sourceCompleteness` |
| Run diagnostics  | `recordType`, `platformErrorCount`, `opportunityCount`, `spreadCandidateCount`, `message`        |

You can download results from Apify datasets as JSON, CSV, Excel, XML, HTML, or
via API. See the official
[Apify dataset documentation](https://docs.apify.com/platform/storage/dataset)
for export and API options.

### How To Use This Luxury Handbag Arbitrage Scraper

1. Select all 4 marketplaces.
2. Leave `Bag models` on Birkin, Kelly, and Chanel Classic Flap.
3. Keep `Targeting mode` on `Broad scan` for the first run.
4. Use a small test run first:
    - `Max listings per marketplace`: `20`
    - `Max pages per marketplace`: `1`
    - `Include unmatched listings`: `true`
5. Open the dataset and check:
    - `run_summary` for counts and marketplace errors.
    - `listing_review` for normalized listings.
    - `watchlist_candidate` for target-like rows.
    - `spread_candidate` for review-worthy spreads blocked by incomplete strict
      fields.
    - `arbitrage_opportunity` for strict cross-platform deal candidates.

For production monitoring, increase `Max listings per marketplace`, increase
`Max pages per marketplace`, and schedule the Actor daily.

### How Much Will a Run Cost?

Run cost depends on your Apify plan, selected marketplaces, scan limits, retry
behavior, and whether Apify Proxy is enabled. This Actor gives you two main cost
controls:

| Setting                       | What it controls                                      | Start here |
| ----------------------------- | ----------------------------------------------------- | ---------- |
| `maxPagesPerPlatform`         | How many result pages are requested per marketplace   | `1`        |
| `maxListingsPerPlatform`      | How many normalized listings are kept per marketplace | `20`       |
| `includeUnmatchedListings`    | Whether diagnostic rows are stored in the dataset     | `true`     |
| `proxyConfiguration`          | Whether Apify Proxy is used                           | disabled   |
| `watchlistMode=strict_target` | Whether the scan is narrowed to one known bag target  | optional   |

Best practice: run a small private test first, inspect the dataset, then
increase pages and listing caps only if the output matches your workflow.

### Example Input

Starter broad scan across all marketplaces:

```json
{
    "platforms": ["vestiaire", "rebag", "fashionphile", "1stdibs"],
    "models": ["birkin", "kelly", "classic_flap"],
    "watchlistMode": "broad_scan",
    "maxListingsPerPlatform": 60,
    "maxPagesPerPlatform": 1,
    "minSpreadPercent": 12,
    "minNetRoiPercent": 8,
    "shippingEstimate": 150,
    "repairBuffer": 250,
    "fxBufferPercent": 2,
    "rebagCommissionPercent": 20,
    "firstDibsCommissionPercent": 20,
    "includeUnmatchedListings": true
}
````

For a deeper daily sourcing run, keep the same fields and increase
`maxPagesPerPlatform` to `3` or `4` after you confirm the first output is useful
for your workflow.

Strict target scan for a known bag:

```json
{
    "platforms": ["vestiaire", "rebag", "fashionphile", "1stdibs"],
    "watchlistMode": "strict_target",
    "watchlistModel": "birkin",
    "watchlistSize": "25",
    "watchlistColor": "black",
    "watchlistMaterial": "togo",
    "watchlistHardware": "gold",
    "watchlistConditionMin": "excellent",
    "watchlistKeywordsText": "noir, GHW, gold hardware",
    "maxListingsPerPlatform": 40,
    "maxPagesPerPlatform": 3,
    "minSpreadPercent": 12,
    "minNetRoiPercent": 8,
    "shippingEstimate": 150,
    "repairBuffer": 250,
    "fxBufferPercent": 2,
    "rebagCommissionPercent": 20,
    "firstDibsCommissionPercent": 20,
    "includeUnmatchedListings": true
}
```

Strict target scan for a Chanel Classic Flap:

```json
{
    "platforms": ["vestiaire", "rebag", "fashionphile", "1stdibs"],
    "watchlistMode": "strict_target",
    "watchlistModel": "classic_flap",
    "watchlistSize": "medium",
    "watchlistColor": "black",
    "watchlistMaterial": "caviar",
    "watchlistHardware": "gold",
    "watchlistConditionMin": "excellent",
    "watchlistKeywordsText": "double flap, GHW",
    "maxListingsPerPlatform": 40,
    "maxPagesPerPlatform": 3,
    "minSpreadPercent": 12,
    "minNetRoiPercent": 8,
    "shippingEstimate": 150,
    "repairBuffer": 250,
    "fxBufferPercent": 2,
    "rebagCommissionPercent": 20,
    "firstDibsCommissionPercent": 20,
    "includeUnmatchedListings": true
}
```

### Input Fields Explained

#### 1. Scan Scope

- `platforms`: resale marketplaces to scan. Default: Vestiaire Collective,
  Rebag, Fashionphile, and 1stDibs.
- `models`: bag families to scan when no strict target is provided. Default:
  Birkin, Kelly, and Chanel Classic Flap.

#### 2. Strict Target (optional)

Use strict target mode when you already know the bag you want to monitor.

![Broad scan versus strict target input mode, using real Actor input field labels](https://api.apify.com/v2/key-value-stores/MEmF9KxfAJPom7iN6/records/broad-vs-strict-input.png?v=20260616-native-text)

- `watchlistMode`: `broad_scan` or `strict_target`.
- `watchlistModel`: Birkin, Kelly, or Chanel Classic Flap.
- `watchlistSize`: examples: `25`, `28`, `30`, `32`, `35`, `40`, `mini`,
  `small`, `medium`, `jumbo`.
- `watchlistColor`: examples: `black`, `noir`, `etoupe`, `gold`, `biscuit`.
- `watchlistMaterial`: examples: `togo`, `epsom`, `clemence`, `swift`,
  `lambskin`, `caviar`, `calfskin`, `exotic`.
- `watchlistHardware`: examples: `gold`, `GHW`, `palladium`, `PHW`,
  `rose gold`, `permabrass`.
- `watchlistConditionMin`: minimum accepted condition bucket.
- `watchlistKeywordsText`: extra comma-separated keywords such as `sellier`,
  `retourne`, `special order`, `full set`, or `GHW`.

#### 3. Scan Limits

- `maxListingsPerPlatform`: the maximum normalized listings kept from each
  marketplace. This is the main output-size cap.
- `maxPagesPerPlatform`: how deep the Actor paginates per marketplace and query.
  More pages can discover more listings, but also makes runs longer.

Simple rule: increase pages when you want deeper discovery, increase listings
when marketplaces return more valid rows than your current cap.

#### 4. Deal Thresholds

The Actor uses two deal gates:

1. `minSpreadPercent`: price gap before costs.
2. `minNetRoiPercent`: estimated profit after costs and sell-side fees.

Example gross spread:

```text
buy listing = $10,000
sell reference = $12,000
gross spread = $2,000
gross spread % = 20%
```

Example estimated net ROI:

```text
landed_buy_cost = (buy_price + shippingEstimate + repairBuffer) * (1 + fxBufferPercent / 100)
estimated_net_profit = estimated_net_sell_value - landed_buy_cost
estimated_net_roi_% = (estimated_net_profit / landed_buy_cost) * 100
```

![Deal thresholds and output record map with real Actor labels](https://api.apify.com/v2/key-value-stores/MEmF9KxfAJPom7iN6/records/roi-output-map.png?v=20260616-native-text)

If a bag passes gross spread but fails net ROI, the Actor excludes it from
`arbitrage_opportunity`. This avoids surfacing deals that look good before fees
but weak after friction.

#### 5. Cost Assumptions (optional)

- `shippingEstimate`: fixed shipping, insurance, or handling cost added to the
  buy price.
- `repairBuffer`: fixed buffer for cleaning, repair, authentication,
  photography, or resale prep.
- `fxBufferPercent`: percentage buffer for FX slippage, taxes, duties, or other
  costs not already included.

These values are intentionally editable because luxury resale economics vary by
country, payment method, shipping route, and risk tolerance.

#### 6. Platform Fee Assumptions (optional)

Vestiaire and Fashionphile use built-in fee logic in the Actor. Rebag and 1stDibs
need your estimated commission because public listing pages do not reveal your
private seller economics.

| Sell platform        | Fee model used by the Actor                                                                     |
| -------------------- | ----------------------------------------------------------------------------------------------- |
| Vestiaire Collective | US/USD seller fee tiers plus payment processing fee.                                            |
| Fashionphile         | Tiered consignment estimate: 30% on the first $3,000, then 15% above $3,000.                    |
| Rebag                | Your `rebagCommissionPercent` assumption.                                                       |
| 1stDibs              | Your `firstDibsCommissionPercent` assumption, plus optional plan cost in API-level assumptions. |

If you only use the Actor for buy-side sourcing, leave the defaults. If you
intend to resell through Rebag or 1stDibs, replace the defaults with your own
actual payout assumptions.

#### 7. Output & Proxy

- `includeUnmatchedListings`: keep listings that could not join a strict match
  group. This is useful for debugging and market research.
- `proxyConfiguration`: optional Apify Proxy settings. Direct requests are the
  default because these marketplaces often work better without proxy. Enable
  proxy only if a marketplace blocks your run. See
  [Apify Proxy docs](https://docs.apify.com/platform/proxy).

### Output Records

The dataset contains mixed records. Filter by `recordType`.

| recordType              | Meaning                                                                                       |
| ----------------------- | --------------------------------------------------------------------------------------------- |
| `arbitrage_opportunity` | Strict cross-platform match group that passed spread and net ROI thresholds.                  |
| `spread_candidate`      | Relaxed cross-platform spread that passed ROI filters but needs manual verification.          |
| `normalized_listing`    | Clean listing row from one marketplace.                                                       |
| `watchlist_candidate`   | Listing that matches your strict target or watchlist logic.                                   |
| `unmatched_listing`     | Listing excluded from strict arbitrage groups, with reasons when available.                   |
| `platform_error`        | Recoverable marketplace error. Other platforms can still succeed.                             |
| `run_summary`           | Final counts by platform and record category. Also saved as `RUN-SUMMARY` in key-value store. |

Dataset views:

- `overview`: compact mixed-record table.
- `opportunity_details`: deal candidate columns.
- `spread_candidates`: relaxed review candidate columns.
- `listing_review`: listing-level review columns.
- `errors_and_summary`: platform errors and final run summary.

### Example Output

Simplified `normalized_listing`:

```json
{
    "recordType": "normalized_listing",
    "platform": "vestiaire",
    "title": "Hermès Birkin 35 leather handbag",
    "model": "birkin",
    "size": "35",
    "colorBucket": "red",
    "materialBucket": "leather",
    "hardwareBucket": "unknown",
    "conditionRaw": "Very good condition",
    "conditionBucket": "very_good",
    "price": 7769,
    "currency": "USD",
    "url": "https://us.vestiairecollective.com/..."
}
```

Simplified `arbitrage_opportunity`:

```json
{
    "recordType": "arbitrage_opportunity",
    "matchKey": "birkin|25|black|togo|gold|excellent",
    "platformsCompared": ["fashionphile", "vestiaire"],
    "grossSpreadPercent": 18.4,
    "sellPlatform": "fashionphile",
    "sellFeeModel": "fashionphile_consignment_official",
    "estimatedNetSellValue": 21650,
    "estimatedNetRoiPercent": 15.36,
    "warnings": ["ROI is an estimate from public listing prices, not guaranteed profit."]
}
```

Simplified `spread_candidate`:

```json
{
    "recordType": "spread_candidate",
    "matchStrictness": "relaxed_model_size_color_condition",
    "relaxedFields": ["materialBucket", "hardwareBucket"],
    "platformsCompared": ["rebag", "vestiaire"],
    "grossSpreadPercent": 128.5,
    "sellPlatform": "vestiaire",
    "estimatedNetRoiPercent": 89.4,
    "reviewWarnings": [
        "Material and/or hardware were relaxed for matching.",
        "Verify exact leather, hardware, photos, condition notes, authenticity, fees, and liquidity before buying."
    ]
}
```

### How Strict Matching Works

The Actor is conservative on purpose. It only creates an `arbitrage_opportunity`
when listings can be compared on core attributes such as model, size, color,
material, hardware, condition, and price.

This means:

- You get fewer opportunities.
- You get fewer bad comparisons.
- Missing hardware, vague leather, unknown condition, or weak title data can
  move a listing into `watchlist_candidate` or `unmatched_listing` instead of
  `arbitrage_opportunity`.
- Useful but imperfect spreads can still appear as `spread_candidate` when the
  model, size, color, and either condition or material are comparable.

For luxury resale, this is usually safer than fuzzy matching. A Birkin 25 black
Togo gold hardware bag is not the same comp as a Birkin 30 black Epsom palladium
hardware bag, and a Chanel Medium Classic Flap black caviar GHW is not the same
comp as a Chanel Jumbo lambskin silver hardware bag.

### Why You Might See 0 Opportunities

`0` opportunities does not mean the Actor failed. It often means the strict deal
engine did its job.

Common reasons:

- The platforms returned listings, but not the same exact attributes.
- A listing was missing hardware, material, condition, or price.
- The gross spread passed, but estimated net ROI failed after fees and costs.
- Only one marketplace had a comparable listing for that exact match key.
- Your thresholds are too high for the current market.
- 1stDibs or another platform exposed limited structured condition data.

Check `run_summary`, then inspect `spread_candidate`, `watchlist_candidate`, and
`unmatched_listing` rows. `spread_candidate` is where the Actor puts spreads
that look interesting but need human verification because material, hardware, or
condition data was relaxed.

### Recommended Workflows

#### Broad Daily Scan

Use this when you want market coverage:

- `watchlistMode`: `broad_scan`
- `models`: Birkin, Kelly, and Classic Flap
- `maxListingsPerPlatform`: `60`
- `maxPagesPerPlatform`: `4`
- Schedule: daily
- Review: `run_summary`, `spread_candidates`, `listing_review`, then
  `opportunity_details`

#### Strict Buyer Watchlist

Use this when a buyer or client wants a specific bag:

- `watchlistMode`: `strict_target`
- Fill model, size, color, material, hardware, and minimum condition.
- Add keywords like `full set`, `sellier`, `retourne`, `GHW`, `PHW`.
- Keep `includeUnmatchedListings` on until your target wording is tuned.

#### Reseller ROI Check

Use this when you already know your selling route:

- Set `shippingEstimate` to your average insured shipping cost.
- Set `repairBuffer` to your usual authentication, cleaning, and prep buffer.
- Set `fxBufferPercent` for taxes, duties, currency friction, and safety margin.
- Replace Rebag and 1stDibs commission defaults with your own payout terms.

### Detailed FAQ

#### Is this a Hermes Birkin scraper, Hermes Kelly scraper, or Chanel Classic Flap scraper?

All three. The Actor supports Hermes Birkin, Hermes Kelly, and Chanel Classic
Flap scanning. It can run broad model searches or a strict target watchlist.

#### I do not know the exact bag yet. Which input should I use?

Start with [Broad scan](#quick-start). Keep `Targeting mode` on `Broad scan`,
select all marketplaces, keep all three bag models, and run with
`Max pages per marketplace = 1`. Then inspect `run_summary` and
`spread_candidate` before narrowing into [Strict target](#2-strict-target-optional).

#### I know the exact buyer request. Which input should I use?

Use [Strict target](#2-strict-target-optional). Fill `Target model`,
`Target size`, `Target color`, `Target leather/material`, `Target hardware`, and
`Minimum condition`. Add `Extra keywords` only when the marketplace wording
matters, for example `sellier`, `retourne`, `full set`, `GHW`, or `PHW`.

#### Does this scrape sold prices?

No. It compares active public asking prices. Asking prices are useful for market
screening, but they are not the same as sold comps or final payout.

#### Does this guarantee profitable arbitrage?

No. It estimates spread and ROI from public listings and user-provided cost
assumptions. You must still verify authenticity, condition, seller terms,
shipping, taxes, liquidity, return policy, and real resale route.

#### Does this authenticate Hermes or Chanel bags?

No. It extracts and normalizes marketplace listing data. It does not authenticate
bags, inspect photos like a specialist, or verify certificates. Use it to build a
shortlist, then do manual authentication and due diligence.

#### Why does condition matter so much?

Condition changes resale value, liquidity, repair costs, and buyer confidence.
The Actor normalizes public condition labels into buckets such as
`new_or_never_worn`, `excellent`, `very_good`, `good`, and `fair` when the source
exposes enough information.

#### Why are there Rebag and 1stDibs fee inputs?

Because your seller economics on those platforms can depend on private quote,
seller plan, category, price, or relationship. The Actor cannot infer your real
payout from public listing pages, so it lets you set your own assumptions.

#### What is the difference between Max listings and Max pages?

`Max pages per marketplace` controls how deep the Actor searches. `Max listings
per marketplace` controls how many normalized rows are kept. Pages affect
discovery depth. Listings affect output size and cost control.

#### What thresholds should I start with?

Start with the defaults: 12% gross spread and 8% estimated net ROI. If you get
too many weak candidates, raise them. If you get no strict opportunities but
useful `spread_candidate` or watchlist rows, inspect those first before lowering
thresholds.

#### Can I use this for Rolex, jewelry, or other luxury items?

Not in this Actor. It is intentionally focused on Hermes Birkin, Hermes Kelly,
and Chanel Classic Flap. A broader luxury resale arbitrage Actor would need
separate normalization rules and fee assumptions.

#### Can I run this on a schedule?

Yes. Use Apify schedules for daily or weekly runs. Daily is the best cadence for
high-demand Birkin/Kelly/Classic Flap inventory because attractive listings can move quickly.
See [Apify schedules](https://docs.apify.com/platform/schedules).

#### Can I export the data to CSV, Excel, Google Sheets, or an API?

Yes. Apify datasets can be downloaded as JSON, CSV, Excel, XML, HTML, or read
through the dataset API. Start with [Output Records](#output-records), then use
the [Apify dataset docs](https://docs.apify.com/platform/storage/dataset) or the
[API Usage](#api-usage) examples below.

#### Can I use this Actor as an API or MCP tool?

Yes. You can run it from Apify Console, Apify API, Apify CLI, schedules,
webhooks, integrations, or MCP-compatible agent workflows. The dataset output can
then feed spreadsheets, Slack alerts, email reports, internal dashboards, or
pricing agents. See [Apify API docs](https://docs.apify.com/api/v2) and
[Apify webhooks](https://docs.apify.com/platform/integrations/webhooks).

#### Is this an official Hermes, Vestiaire, Rebag, Fashionphile, or 1stDibs API?

No. This is an independent Apify Actor that reads public listing pages and turns
them into a structured dataset. It is useful when you need a repeatable luxury
handbag resale monitoring workflow, but it is not an official marketplace API.

#### Which output should I monitor first?

Start with `run_summary`, then inspect `spread_candidate`. In luxury resale,
strict opportunities can be rare because model, size, leather, color, hardware,
condition, and price all need to line up. `spread_candidate` is intentionally
more useful for human review because it keeps promising spreads visible when one
or two marketplace attributes are incomplete.

#### Why is `arbitrage_opportunity` stricter than `spread_candidate`?

`arbitrage_opportunity` is reserved for stricter comparable groups that passed
both deal thresholds. `spread_candidate` keeps useful but imperfect spreads
visible when a marketplace has incomplete material, hardware, or condition data.
For sourcing, review `spread_candidate` first, then manually verify exact leather,
hardware, photos, condition notes, authenticity, fees, and liquidity.

#### Why are some attributes unknown?

Marketplace search pages do not always expose complete structured data. The
Actor enriches condition from detail pages where practical, but some fields can
still be unknown. Strict matching excludes weak comps instead of pretending they
are exact matches.

#### Is this legal?

This Actor reads public listing data and does not log into user accounts, buy
items, reserve items, or message sellers. You are responsible for complying with
marketplace terms, local laws, and your own resale obligations.

### Troubleshooting

| Problem                       | What to check                                                                                                                           |
| ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| No opportunities              | Inspect `run_summary`, `spread_candidate`, `watchlist_candidate`, and `unmatched_listing`. Strict matching may be excluding weak comps. |
| Marketplace error             | Check `platform_error`. Other marketplaces can still succeed. Retry later or reduce scan depth.                                         |
| Too many rows                 | Lower `maxListingsPerPlatform`, lower `maxPagesPerPlatform`, or switch to strict target mode.                                           |
| Too few rows                  | Increase `maxPagesPerPlatform`, increase `maxListingsPerPlatform`, or broaden target fields.                                            |
| ROI looks too optimistic      | Increase `shippingEstimate`, `repairBuffer`, `fxBufferPercent`, or commission assumptions.                                              |
| Rebag/1stDibs ROI seems wrong | Replace default commission assumptions with your real seller payout terms.                                                              |
| Dataset feels mixed           | Filter by `recordType` or use the dataset views.                                                                                        |

### API Usage

You can run the Actor through Apify API, CLI, schedules, webhooks, integrations,
or the Console UI. This is useful when you want a repeatable luxury handbag
resale price monitor instead of a one-off manual search.

Example CLI call:

```bash
apify call kazkn/hermes-birkin-kelly-arbitrage --input '{
  "platforms": ["vestiaire", "rebag", "fashionphile", "1stdibs"],
  "models": ["birkin", "kelly", "classic_flap"],
  "maxPagesPerPlatform": 1,
  "maxListingsPerPlatform": 20,
  "includeUnmatchedListings": true
}'
```

JavaScript client:

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });

const run = await client.actor('kazkn/hermes-birkin-kelly-arbitrage').call({
    platforms: ['vestiaire', 'rebag', 'fashionphile', '1stdibs'],
    models: ['birkin', 'kelly', 'classic_flap'],
    maxPagesPerPlatform: 1,
    maxListingsPerPlatform: 60,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((item) => item.recordType === 'spread_candidate'));
```

Python client:

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])

run = client.actor("kazkn/hermes-birkin-kelly-arbitrage").call(
    run_input={
        "platforms": ["vestiaire", "rebag", "fashionphile", "1stdibs"],
        "models": ["birkin", "kelly", "classic_flap"],
        "maxPagesPerPlatform": 1,
        "maxListingsPerPlatform": 60,
    }
)

items = client.dataset(run["defaultDatasetId"]).list_items().items
spread_candidates = [
    item for item in items if item.get("recordType") == "spread_candidate"
]
print(spread_candidates)
```

Dataset API endpoint:

```text
https://api.apify.com/v2/datasets/[DATASET_ID]/items?format=json
```

Common automation patterns:

- Daily scheduled run into Google Sheets or Airtable.
- Slack or email alert when `arbitrage_opportunity` or high-ROI `spread_candidate` rows appear.
- Webhook that sends the dataset to your own pricing dashboard.
- MCP or agent workflow that checks a strict target before a sourcing decision.
- API workflow that stores `run_summary` and tracks market movement over time.

### Cost And Performance Tips

- Start with `maxPagesPerPlatform = 1` and `maxListingsPerPlatform = 20`.
- Increase limits only after the output format matches your workflow.
- Keep `includeUnmatchedListings = true` while tuning, then turn it off if you
  only want deal candidates and summaries.
- Direct requests are the default. Enable proxy only when a marketplace blocks a
  run.
- Daily scheduled scans are usually more useful than very deep one-off scans.

### Reliability Notes

This Actor is designed so one marketplace can fail without hiding results from
the others. If a source is temporarily blocked or changes its page layout, the
dataset can still contain successful listings plus a `platform_error` row for
the failed source.

For stable scheduled monitoring:

- Keep the default or starter input small enough to finish quickly.
- Review `run_summary` on every scheduled run.
- Treat sudden drops in one marketplace as a source-health signal, not
  necessarily a market signal.
- Report broken selectors or wrong fields in the Actor Issues tab with a run ID.

### Limitations

- Public listing prices are asking prices, not final sale prices.
- Marketplace fees, shipping, insurance, repairs, taxes, FX, import duties, and
  seller negotiation can change real economics.
- Strict matching intentionally produces fewer opportunities than broad fuzzy
  matching.
- The Actor does not authenticate goods, detect counterfeits, or inspect photos.
- The Actor does not buy items, reserve items, negotiate, or message sellers.
- Some marketplaces expose limited structured data, especially condition and
  hardware.
- This Actor does not provide investment, financial, legal, tax, or resale
  business advice.

### Support

Use the Apify Issues tab if a marketplace breaks, a field looks wrong, or you
need another output column. Include the run ID, input settings, and a short
description of what looked wrong.

Custom extensions can be built from this Actor, for example:

- More resale marketplaces.
- Slack or email alerts for one strict watchlist.
- Google Sheets export with daily deltas.
- Sold-comps enrichment if a reliable source is available.

### Related KazKN Actors

If you also source or monitor broader second-hand marketplaces, these KazKN
Actors are the closest complements:

| Actor                                                                | Use it when                                                                                                      |
| -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| [Vinted Smart Scraper](https://apify.com/kazkn/vinted-smart-scraper) | You need structured Vinted listing data for broader second-hand sourcing, resale monitoring, or market research. |
| [Vinted Turbo Scraper](https://apify.com/kazkn/vinted-turbo-scraper) | You want a faster Vinted-focused scan for high-volume marketplace discovery.                                     |
| [KazKN Apify profile](https://apify.com/kazkn)                       | You want to see the full set of KazKN Actors and new scraper releases.                                           |

### Search Terms This Actor Covers

This Actor is built for users searching for a Hermes Birkin scraper, Hermes Kelly
scraper, Chanel Classic Flap scraper, Birkin resale price monitor, Kelly resale
price monitor, Chanel Classic Flap price monitor, Vestiaire Collective scraper,
Rebag scraper, Fashionphile scraper, 1stDibs scraper, luxury handbag arbitrage
tool, pre-owned Hermes price comparison dataset, Chanel resale dataset, designer
handbag resale data, Hermes condition normalization, Chanel caviar lambskin
normalization, Birkin price comparison API, Kelly price alert, luxury resale
watchlist, Apify luxury scraper, or MCP luxury handbag price monitor.

# Actor input Schema

## `platforms` (type: `array`):

Pick the resale platforms to compare. Start with all four for cross-platform spreads, or narrow the scan while testing.

## `models` (type: `array`):

Choose the bag families to scan when no strict watchlist is provided.

## `watchlistMode` (type: `string`):

Broad scan searches all selected model families. Strict target limits the scan to the simple fields below.

## `watchlistModel` (type: `string`):

Used only when targeting mode is Strict target.

## `watchlistSize` (type: `string`):

Optional. Examples: 25, 28, 30, 32, 35, mini, small, medium, jumbo.

## `watchlistColor` (type: `string`):

Optional. Examples: black, noir, etoupe, gold, biscuit.

## `watchlistMaterial` (type: `string`):

Optional. Examples: togo, epsom, clemence, swift, lambskin, caviar, calfskin.

## `watchlistHardware` (type: `string`):

Optional. Examples: gold, GHW, palladium, PHW, rose gold, permabrass.

## `watchlistConditionMin` (type: `string`):

Optional. Lowest condition accepted for the strict target.

## `watchlistKeywordsText` (type: `string`):

Optional. Separate terms with commas or new lines. Examples: sellier, retourne, special order, GHW.

## `maxListingsPerPlatform` (type: `integer`):

Hard cap on normalized listings collected from each selected marketplace. Lower values keep private smoke runs cheap.

## `maxPagesPerPlatform` (type: `integer`):

Maximum result pages requested per marketplace and query.

## `minSpreadPercent` (type: `number`):

First gate. Example: buy at $10,000 and compare against a $12,000 listing = 20% price gap before costs.

## `minNetRoiPercent` (type: `number`):

Second gate. Estimated profit after fees and costs divided by landed buy cost. Example: $1,000 profit on $10,000 landed cost = 10%.

## `shippingEstimate` (type: `number`):

Estimated fixed shipping, insurance, or handling cost added to the buy price for each potential deal.

## `repairBuffer` (type: `number`):

Extra fixed safety buffer for cleaning, repair, authentication, photography, or prep before resale.

## `fxBufferPercent` (type: `number`):

Extra percentage added to landed buy cost for FX slippage, import friction, or taxes not already included.

## `rebagCommissionPercent` (type: `number`):

Rebag commissions are quote-specific, so this is your assumption for Rebag-as-sell-channel ROI. Official guidance says many items land around 15-25%, with some as low as 8%.

## `firstDibsCommissionPercent` (type: `number`):

1stDibs commissions depend on seller plan, category, price, and business type. Use your own seller-plan estimate here.

## `includeUnmatchedListings` (type: `boolean`):

Emit listings that cannot be placed in a strict cross-platform match group.

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

Optional. Disabled by default because these marketplaces often work better with direct requests. Enable Apify Proxy only if your run is blocked.

## Actor input object example

```json
{
  "platforms": [
    "vestiaire",
    "rebag",
    "fashionphile",
    "1stdibs"
  ],
  "models": [
    "birkin",
    "kelly",
    "classic_flap"
  ],
  "watchlistMode": "broad_scan",
  "watchlistModel": "birkin",
  "maxListingsPerPlatform": 60,
  "maxPagesPerPlatform": 4,
  "minSpreadPercent": 12,
  "minNetRoiPercent": 8,
  "shippingEstimate": 150,
  "repairBuffer": 250,
  "fxBufferPercent": 2,
  "rebagCommissionPercent": 20,
  "firstDibsCommissionPercent": 20,
  "includeUnmatchedListings": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `runSummary` (type: `string`):

Final run summary stored as RUN-SUMMARY in the default key-value store.

## `datasetItems` (type: `string`):

All rows emitted by the Actor: 💎 strict deal candidates, 🔍 spread candidates to review, 👜 normalized listings, 🎯 watchlist candidates, 🧾 unmatched listings, ⚠️ platform errors, and 📊 run summary.

# 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 = {
    "platforms": [
        "vestiaire",
        "rebag",
        "fashionphile",
        "1stdibs"
    ],
    "models": [
        "birkin",
        "kelly",
        "classic_flap"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("kazkn/hermes-birkin-kelly-arbitrage").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 = {
    "platforms": [
        "vestiaire",
        "rebag",
        "fashionphile",
        "1stdibs",
    ],
    "models": [
        "birkin",
        "kelly",
        "classic_flap",
    ],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("kazkn/hermes-birkin-kelly-arbitrage").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 '{
  "platforms": [
    "vestiaire",
    "rebag",
    "fashionphile",
    "1stdibs"
  ],
  "models": [
    "birkin",
    "kelly",
    "classic_flap"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call kazkn/hermes-birkin-kelly-arbitrage --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=kazkn/hermes-birkin-kelly-arbitrage",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Hermes Birkin/Kelly & Chanel Classic Cross-Platform Arbitrage",
        "description": "Find resale spread candidates for Hermes Birkin/Kelly and Chanel Classic Flap across Vestiaire, Rebag, Fashionphile, and 1stDibs. Normalize condition, size, material, hardware, price, and estimated ROI for daily sourcing workflows.",
        "version": "0.0",
        "x-build-id": "RMbrMk3wxP2EZx7cU"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/kazkn~hermes-birkin-kelly-arbitrage/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-kazkn-hermes-birkin-kelly-arbitrage",
                "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/kazkn~hermes-birkin-kelly-arbitrage/runs": {
            "post": {
                "operationId": "runs-sync-kazkn-hermes-birkin-kelly-arbitrage",
                "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/kazkn~hermes-birkin-kelly-arbitrage/run-sync": {
            "post": {
                "operationId": "run-sync-kazkn-hermes-birkin-kelly-arbitrage",
                "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": {
                    "platforms": {
                        "title": "🛍️ Marketplaces to scan",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Pick the resale platforms to compare. Start with all four for cross-platform spreads, or narrow the scan while testing.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "vestiaire",
                                "rebag",
                                "fashionphile",
                                "1stdibs"
                            ],
                            "enumTitles": [
                                "🟣 Vestiaire Collective",
                                "👜 Rebag",
                                "💼 Fashionphile",
                                "🏛️ 1stDibs"
                            ]
                        }
                    },
                    "models": {
                        "title": "👜 Bag models",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Choose the bag families to scan when no strict watchlist is provided.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "birkin",
                                "kelly",
                                "classic_flap"
                            ],
                            "enumTitles": [
                                "💎 Birkin",
                                "🔒 Kelly",
                                "🖤 Chanel Classic Flap"
                            ]
                        }
                    },
                    "watchlistMode": {
                        "title": "🎯 Targeting mode",
                        "enum": [
                            "broad_scan",
                            "strict_target"
                        ],
                        "type": "string",
                        "description": "Broad scan searches all selected model families. Strict target limits the scan to the simple fields below.",
                        "default": "broad_scan"
                    },
                    "watchlistModel": {
                        "title": "👜 Target model",
                        "enum": [
                            "birkin",
                            "kelly",
                            "classic_flap"
                        ],
                        "type": "string",
                        "description": "Used only when targeting mode is Strict target.",
                        "default": "birkin"
                    },
                    "watchlistSize": {
                        "title": "📏 Target size (optional)",
                        "type": "string",
                        "description": "Optional. Examples: 25, 28, 30, 32, 35, mini, small, medium, jumbo."
                    },
                    "watchlistColor": {
                        "title": "🎨 Target color (optional)",
                        "type": "string",
                        "description": "Optional. Examples: black, noir, etoupe, gold, biscuit."
                    },
                    "watchlistMaterial": {
                        "title": "🧵 Target leather/material (optional)",
                        "type": "string",
                        "description": "Optional. Examples: togo, epsom, clemence, swift, lambskin, caviar, calfskin."
                    },
                    "watchlistHardware": {
                        "title": "✨ Target hardware (optional)",
                        "type": "string",
                        "description": "Optional. Examples: gold, GHW, palladium, PHW, rose gold, permabrass."
                    },
                    "watchlistConditionMin": {
                        "title": "✅ Minimum condition (optional)",
                        "enum": [
                            "new_or_never_worn",
                            "excellent",
                            "very_good",
                            "good",
                            "fair"
                        ],
                        "type": "string",
                        "description": "Optional. Lowest condition accepted for the strict target."
                    },
                    "watchlistKeywordsText": {
                        "title": "🔎 Extra keywords (optional)",
                        "type": "string",
                        "description": "Optional. Separate terms with commas or new lines. Examples: sellier, retourne, special order, GHW."
                    },
                    "maxListingsPerPlatform": {
                        "title": "🧮 Max listings per marketplace",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Hard cap on normalized listings collected from each selected marketplace. Lower values keep private smoke runs cheap.",
                        "default": 60
                    },
                    "maxPagesPerPlatform": {
                        "title": "📄 Max pages per marketplace",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "Maximum result pages requested per marketplace and query.",
                        "default": 4
                    },
                    "minSpreadPercent": {
                        "title": "💰 Minimum price gap before costs %",
                        "minimum": 0,
                        "maximum": 500,
                        "type": "number",
                        "description": "First gate. Example: buy at $10,000 and compare against a $12,000 listing = 20% price gap before costs.",
                        "default": 12
                    },
                    "minNetRoiPercent": {
                        "title": "📈 Minimum profit after costs %",
                        "minimum": 0,
                        "maximum": 500,
                        "type": "number",
                        "description": "Second gate. Estimated profit after fees and costs divided by landed buy cost. Example: $1,000 profit on $10,000 landed cost = 10%.",
                        "default": 8
                    },
                    "shippingEstimate": {
                        "title": "🚚 Shipping/insurance estimate (optional)",
                        "minimum": 0,
                        "maximum": 100000,
                        "type": "number",
                        "description": "Estimated fixed shipping, insurance, or handling cost added to the buy price for each potential deal.",
                        "default": 150
                    },
                    "repairBuffer": {
                        "title": "🧼 Repair/authentication buffer (optional)",
                        "minimum": 0,
                        "maximum": 100000,
                        "type": "number",
                        "description": "Extra fixed safety buffer for cleaning, repair, authentication, photography, or prep before resale.",
                        "default": 250
                    },
                    "fxBufferPercent": {
                        "title": "🌍 FX/tax buffer % (optional)",
                        "minimum": 0,
                        "maximum": 100,
                        "type": "number",
                        "description": "Extra percentage added to landed buy cost for FX slippage, import friction, or taxes not already included.",
                        "default": 2
                    },
                    "rebagCommissionPercent": {
                        "title": "👜 Rebag estimated commission % (optional)",
                        "minimum": 0,
                        "maximum": 99.99,
                        "type": "number",
                        "description": "Rebag commissions are quote-specific, so this is your assumption for Rebag-as-sell-channel ROI. Official guidance says many items land around 15-25%, with some as low as 8%.",
                        "default": 20
                    },
                    "firstDibsCommissionPercent": {
                        "title": "🏛️ 1stDibs estimated commission % (optional)",
                        "minimum": 0,
                        "maximum": 99.99,
                        "type": "number",
                        "description": "1stDibs commissions depend on seller plan, category, price, and business type. Use your own seller-plan estimate here.",
                        "default": 20
                    },
                    "includeUnmatchedListings": {
                        "title": "🧾 Include unmatched listings",
                        "type": "boolean",
                        "description": "Emit listings that cannot be placed in a strict cross-platform match group.",
                        "default": true
                    },
                    "proxyConfiguration": {
                        "title": "🌐 Proxy settings",
                        "type": "object",
                        "description": "Optional. Disabled by default because these marketplaces often work better with direct requests. Enable Apify Proxy only if your run is blocked."
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
