# Cardmarket Repricer - Find Every Mispriced Card You Sell (`lowlanddata/cardmarket-repricer`) Actor

Your Cardmarket prices were right the day you listed them, and the market has moved since. Feed in your stock export and get back only the cards whose price is now out of line: what you charge, what it is worth today, what to charge, and which rule decided. Reads the official and community exports.

- **URL**: https://apify.com/lowlanddata/cardmarket-repricer.md
- **Developed by:** [Lowland Data](https://apify.com/lowlanddata) (community)
- **Categories:** E-commerce, MCP servers, Agents
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.85 / 1,000 card repriceds

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

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

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## Cardmarket Repricer - Find Every Mispriced Card You Sell

Your prices were right the day you listed them. The market has moved since, and you have no way of knowing which cards moved with it. Some of your stock now sits above the market and will not sell. Some sits below it and is costing you money on every sale. With a few thousand cards listed, there is no version of checking by hand.

This tells you **exactly which of your cards are priced wrong, and what to charge instead.** Give it your stock export; it returns one row per card that is out of line, with your price, today's market price, the suggested price, and which rule decided. Nothing else. A run on a 3,000-card shop typically comes back with a couple of hundred rows, which is an evening's work turned into a five-minute review.

**Live health record:** [lowlanddata.com/status/cardmarket-repricer](https://lowlanddata.com/status/cardmarket-repricer/) - 30-day success rate and daily canary results, failures included. Full input/output reference: [tool page](https://lowlanddata.com/tools/cardmarket-repricer/).

It reads the price-guide files Cardmarket publishes itself, every day, for all 21 games. It never asks for your login, never touches your account, and never looks at another seller's offers.

### Is this the tool you want?

Four things here read Cardmarket prices, and they answer different questions:

| You want to know                       | Use                                                                            |
| -------------------------------------- | ------------------------------------------------------------------------------ |
| **Which of MY cards are priced wrong** | this one                                                                       |
| What every card in a game is worth     | [Cardmarket Price Guide](https://apify.com/lowlanddata/cardmarket-price-guide) |
| Which cards are cheap to buy right now | [Cardmarket Deal Finder](https://apify.com/lowlanddata/cardmarket-deal-finder) |
| What the market is doing this week     | [TCG Price Movers](https://apify.com/lowlanddata/tcg-price-movers)             |

The Price Guide gives you *every* price. This one only speaks about *your* stock, and only about the cards where your price and the market disagree.

### What a run actually gives you

Four cards from a real shop, repriced against today's guide:

| Card                       | You charge | Market | Suggested | Why                |
| -------------------------- | ---------: | -----: | --------: | ------------------ |
| Sceptile \[Leaf Blade] (EX) |      13.87 |  12.61 | **10.78** | repriced           |
| Ludicolo (GD)              |       2.62 |   2.92 |  **2.10** | repriced           |
| Giant Growth (EX)          |       1.00 |   0.88 |  **0.75** | capped at 25%      |
| Signed Shock (NM)          |      40.00 |  12.50 |         - | signed, left alone |

The first two were quietly above the market and would have sat there. The third was capped because no single run is allowed to move a price more than a quarter. The fourth was skipped, because a signature is not something a price guide ever measured.

### First, how to get your stock file

Worth stating plainly, because it is the part that confuses people: **Cardmarket has no "export my stock to CSV" button.** Two routes actually work:

1. **The API export.** `POST /ws/v2.0/exports/stock`, then poll and download. It returns a **JSON array of Article entities**. This actor reads that format directly, so you can paste it in as-is. One export per game per hour.
2. **A community stock exporter.** Several browser extensions walk your stock pages and write a CSV, because the web UI caps unsorted stock views and has no bulk export. Their CSVs are read here too.

The old API endpoint that produced the classic 18-column `idArticle;idProduct;English Name;...` CSV is deprecated, but plenty of tools still speak it and this actor still reads it.

Whatever the shape, **the file must carry `idProduct`.** That is the only thing a price can be matched on with certainty; see below.

### Quick start (60 seconds)

1. Paste your stock export into **Your stock file** - CSV or JSON, both work. Or give a link to it.
2. Pick the game, and the price you want to sit against: **trend**, 7-day average, 30-day average, or the lowest current offer.
3. Set your undercut, in percent or cents. Hit **Start**.

You get back only the cards that should move. Review them, then apply the ones you agree with.

### What you get

One row per card, with the arithmetic shown rather than hidden:

```json
{
  "idProduct": 273540,
  "idArticle": "1036411276",
  "cardName": "Sceptile [Leaf Blade | Power Poison]",
  "condition": "EX",
  "language": "1",
  "isFoil": false,
  "quantity": 1,
  "currentPriceEur": 13.87,
  "referencePriceEur": 12.61,
  "suggestedPriceEur": 10.78,
  "changeEur": -3.09,
  "changePct": -22.3,
  "reason": "repriced",
  "priceGuideDate": "2026-09-13",
  "stockRow": 3
}
```

`referencePriceEur` is Cardmarket's own figure before your rules. `suggestedPriceEur` is after the condition ladder, your undercut, and the safety rails. `reason` tells you which rule decided it:

| reason                    | what happened                                       |
| ------------------------- | --------------------------------------------------- |
| `repriced`                | your rules produced a new price                     |
| `already-at-target`       | it is where you want it; nothing to do              |
| `held-at-floor`           | the rules wanted lower, the floor stopped them      |
| `capped-by-max-change`    | the move was bigger than one run is allowed to make |
| `signed-card-left-alone`  | signed, so the guide never priced this object       |
| `altered-card-left-alone` | altered, same reason                                |
| `no-price-published`      | Cardmarket has no price for that card yet           |
| `no-foil-price-published` | it has a regular price but no foil price            |
| `no-price-guide-entry`    | the product id is not in the guide at all           |

### The three things worth knowing before you trust it

**It matches on product id, and refuses to guess.** Every row is priced against the `idProduct` in your file. It never falls back to matching by card name, because a bracketed variant or a reprint would quietly price the wrong card, and a wrong price in your shop is your money. If your export has no product id column, the run tells you so instead of pricing it anyway.

**The condition ladder is ours, not Cardmarket's.** Cardmarket publishes one price per card plus a separate foil price. It publishes **nothing per condition**. So every repricer, this one included, invents its own multipliers. The defaults are MT 1.05, NM 1, EX 0.9, GD 0.8, LP 0.7, PL 0.6, PO 0.5, and you should override them if you price differently. Anyone claiming condition-accurate Cardmarket prices is applying their own ladder too; the difference is whether they tell you.

**The safety rails are on by default**, because the failure that matters is not an empty result, it is a shop repriced wrongly overnight:

- a **floor** at 60% of the reference price, so a thin market cannot drag a card down
- an **absolute minimum** of EUR 0.02, which is Cardmarket's own minimum
- a **cap of 25%** on how far any single run may move a price
- **signed and altered cards skipped entirely** - no multiplier makes a signature go away

Turn them off deliberately if you want; they will not turn themselves off.

### Applying the results

This actor suggests. It does not write to your account, and that is on purpose: it needs no credentials from you, so there is nothing of yours to leak.

To apply, feed the rows back through whatever you already use - the Cardmarket API's `PUT /ws/v2.0/stock`, or the extension you exported with. Two traps worth knowing, neither of them ours:

- **`idArticle` is not stable.** Cardmarket re-issues it when a listing is edited. Every row here also carries `idProduct`, `condition`, `language` and `isFoil` so you can rebind a row whose article id has moved.
- **A partial update resets what you leave out.** On `PUT /stock`, an omitted condition defaults to Near Mint and omitted flags default to false. Send the whole article, not just the new price.

### What it costs

| Event             | Price   | When it is charged         |
| ----------------- | ------- | -------------------------- |
| **Card repriced** | $0.0019 | Per row delivered          |
| **Actor start**   | $0.005  | Per run, whatever it finds |

Live prices are always the ones on this page's Pricing tab. Because **Only return cards whose price should move** is on by default, you pay for decisions rather than for a copy of your own stock: a 3,000-card shop where 200 cards drifted costs about 40 cents to reprice, not $5.97. Repricing tools that do this as a subscription start around EUR 5 a month and run to EUR 120 plus a percentage of every sale.

### Input reference

| Field                   | Default   | What it does                                            |
| ----------------------- | --------- | ------------------------------------------------------- |
| `stockCsv` / `stockUrl` | -         | Your export, pasted in or linked. CSV or JSON.          |
| `game`                  | `pokemon` | Which price guide to load.                              |
| `reference`             | `trend`   | What to price against: `trend`, `avg7`, `avg30`, `low`. |
| `undercutPct`           | `5`       | Sit this far below the reference.                       |
| `undercutCents`         | `0`       | A flat amount off as well.                              |
| `floorPct`              | `60`      | Never price below this share of the reference.          |
| `minPriceEur`           | `0.02`    | Absolute minimum, and Cardmarket's own floor.           |
| `maxChangePct`          | `25`      | Most a single run may move a price. `0` disables it.    |
| `roundToCents`          | `1`       | `5` lands on 0.05, `10` on 0.10.                        |
| `conditionMultipliers`  | see above | Your own ladder, as `{"NM": 1, "EX": 0.88}`.            |
| `onlyChanged`           | `true`    | Only return cards that should move.                     |

### Honest limits

- **The guide is one file a day.** Running more often than daily reprices against the same numbers.
- **Language does not change the suggestion.** Cardmarket publishes no per-language price, and a Japanese card can be worth a multiple of its English twin. Your `language` value is carried through untouched so you can filter on it, but nothing here prices it.
- **`low` is not condition-filtered on the non-foil side**, so pricing against the lowest current offer can chase a played copy. `trend` is the steadier choice, which is why it is the default.
- **Playsets** were retired by Cardmarket in November 2024. Old exports still carry the column, and a playset row is priced as four cards.
- **Your file is a snapshot.** Cards sell between exporting and applying. Re-export rather than applying a file from last week.
- Sealed product is not covered; this reads the singles guide.

### Is this allowed, and what about my data

Yes. Cardmarket's terms permit using its interfaces to manage **your own stock**, which is exactly what this does: your inventory in, your suggested prices out. It does not crawl other sellers' offers, which is the activity that actually gets accounts throttled.

Your stock file is read during the run and nothing is kept. The results land in **your** Apify dataset, under your retention settings. There is no login, no API key of yours, and no seller or buyer identity anywhere in the output.

### More tools from Lowland Data

| Tool                                                                           | What it does                                               |
| ------------------------------------------------------------------------------ | ---------------------------------------------------------- |
| [Cardmarket Price Guide](https://apify.com/lowlanddata/cardmarket-price-guide) | The full daily price table for a game                      |
| [TCG Price Movers](https://apify.com/lowlanddata/tcg-price-movers)             | What is moving right now, or an alert when your cards move |
| [Cardmarket Deal Finder](https://apify.com/lowlanddata/cardmarket-deal-finder) | Live offers priced under a card's own trend                |

### Support

A file that will not parse, a rule you need, a game missing? Open an issue on the **Issues** tab with the run id, or write to <contact@lowlanddata.com>. Reports get read the same day.

# Actor input Schema

## `stockCsv` (type: `string`):

Your stock, exported from Cardmarket. Paste it here: the API's JSON export, or a CSV from a stock exporter. It must carry the idProduct column, which is what each card is priced against.

## `stockUrl` (type: `string`):

A direct link to the same file, if you would rather not paste it. Must be reachable without a login.

## `game` (type: `string`):

Which game your stock is in. The price guide for it is loaded once per run.

## `reference` (type: `string`):

Cardmarket's own figure your prices are set against.

## `undercutPct` (type: `integer`):

Sit this far below the reference price.

## `undercutCents` (type: `integer`):

A flat amount taken off as well, if you price that way.

## `floorPct` (type: `integer`):

A hard floor. A thin market or an odd guide entry cannot drag a card below this.

## `minPriceEur` (type: `string`):

Absolute minimum price for any card.

## `maxChangePct` (type: `integer`):

Caps how far a single run can move any price. 0 turns the cap off.

## `roundToCents` (type: `integer`):

1 for exact cents, 5 to land on 0.05, 10 on 0.10.

## `conditionMultipliers` (type: `object`):

Cardmarket publishes one price per card, not one per condition, so the ladder is yours. Defaults: MT 1.05, NM 1, EX 0.9, GD 0.8, LP 0.7, PL 0.6, PO 0.5.

## `onlyChanged` (type: `boolean`):

On by default, so you pay for decisions rather than for a copy of your stock.

## `maxItems` (type: `integer`):

Stop after this many rows.

## Actor input object example

```json
{
  "game": "pokemon",
  "reference": "trend",
  "undercutPct": 5,
  "undercutCents": 0,
  "floorPct": 60,
  "minPriceEur": "0.02",
  "maxChangePct": 25,
  "roundToCents": 1,
  "onlyChanged": true,
  "maxItems": 5000
}
```

# Actor output Schema

## `prices` (type: `string`):

One row per card whose price is out of line with the market: what you charge, what it is worth today, what to charge, and which rule decided.

# 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 = {
    "game": "pokemon",
    "reference": "trend"
};

// Run the Actor and wait for it to finish
const run = await client.actor("lowlanddata/cardmarket-repricer").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 = {
    "game": "pokemon",
    "reference": "trend",
}

# Run the Actor and wait for it to finish
run = client.actor("lowlanddata/cardmarket-repricer").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "game": "pokemon",
  "reference": "trend"
}' |
apify call lowlanddata/cardmarket-repricer --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lowlanddata/cardmarket-repricer"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/FEE1xeZnd1BriNbgL/builds/hhseLTTIqHWQrsJdC/openapi.json
