Developers

CardMetrics public API

TCG card prices in EUR and USD, as friction-free JSON: the same data that powers CardMetrics (Magic, Pokémon, Yu-Gi-Oh!, Lorcana, One Piece, Star Wars: Unlimited and Digimon), with history ingested daily.

Get started in 30 seconds

The prices endpoint is anonymous — no account or API key needed. Pass it up to 100 comma-separated card ids (mind the trailing slash before the query string — without it you get a 301 redirect):

curl "https://cards.faseconsulting.es/api/public/prices/?ids=0948e6dc-8af7-45d3-91de-a2aebee83e82"

Response 200:

{
  "prices": [
    {
      "providerId": "0948e6dc-8af7-45d3-91de-a2aebee83e82",
      "amount": 4360.36,
      "currency": "EUR",
      "source": "cardmarket",
      "capturedAt": "2026-07-11T03:58:15.052Z"
    }
  ]
}

Endpoint reference

GET /api/public/prices/

No authentication

Latest known price for a batch of cards. Ids without a price are simply absent from the response.

Parameters

  • ids — required. 1 to 100 comma-separated providerIds (allowed characters: A–Z a–z 0–9 _ -).

Errors

  • 400 — ids missing, empty, >100 ids, or invalid characters.

Responses are CDN-cacheable: Cache-Control: public, s-maxage=300, stale-while-revalidate=600.

GET /api/public/cards/{providerId}/

Requires API key (Bearer)

Full record of one card printing + its latest price. providerId accepts up to 80 characters (A–Z a–z 0–9 _ - : .).

Request:

curl "https://cards.faseconsulting.es/api/public/cards/0948e6dc-8af7-45d3-91de-a2aebee83e82/" \
     -H "Authorization: Bearer cm_YOUR_API_KEY"

Response 200:

{
  "providerId": "0948e6dc-8af7-45d3-91de-a2aebee83e82",
  "game": "mtg",
  "name": "Black Lotus",
  "setCode": "ced",
  "setName": "Collectors' Edition",
  "number": "233",
  "rarity": "rare",
  "language": "en",
  "printing": "standard",
  "imageUrl": "https://cards.scryfall.io/normal/front/0/9/0948e6dc-8af7-45d3-91de-a2aebee83e82.jpg?1782756162",
  "latest": {
    "source": "cardmarket",
    "currency": "EUR",
    "amount": 4360.36,
    "capturedAt": "2026-07-11T03:58:15.052Z"
  }
}

Errors

  • 400{"error":"invalid_provider_id"}
  • 401 — missing Authorization header, or unknown/revoked/expired key:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api"

{"error":"missing_authorization"}
  • 404{"error":"not_found"}
  • 429{"error":"rate_limited"} + Retry-After

GET /api/public/movers/

No authentication

Top gaining or falling cards — the same query behind the movers pages, with a small cap designed for bots and embeds. Ranking is by percent change; each row carries its own currency (a row's change never mixes EUR and USD).

Parameters

  • game — optional. One of: mtg · pokemon · yugioh · lorcana · onepiece · swu · digimon. Unknown values → cross-game ranking (no 400).
  • directionup | down (default up).
  • window7 | 30 | 90 days (default 7).
  • limit — 1–10 (default 5).

Forgiving contract: any invalid parameter falls back to its default instead of answering 400. The path field is locale-less — prefix /es/, /en/… when linking.

Request:

curl "https://cards.faseconsulting.es/api/public/movers/?limit=1"

Response 200:

{
  "window": 7,
  "direction": "up",
  "movers": [
    {
      "providerId": "swshp-SWSH153",
      "game": "pokemon",
      "name": "Pikachu",
      "setCode": "swshp",
      "setName": "SWSH Black Star Promos",
      "number": "SWSH153",
      "imageUrl": "https://images.pokemontcg.io/swshp/SWSH153_hires.png",
      "currency": "EUR",
      "currentAmount": 129.05,
      "priorAmount": 11.25,
      "pctChange": 1047.111111111111,
      "path": "/pokemon/swshp/pikachu-SWSH153/"
    }
  ]
}

CDN cache: Cache-Control: public, s-maxage=600, stale-while-revalidate=3600.

GET /api/public/card-summary/

No authentication

One-card summary: identity + primary quote, secondary quote in the other currency, and 30-day change. The primary quote is the deepest coherent price series (single source and currency); the secondary is the best series in the OTHER currency and is omitted (null) when stale for more than 14 days. delta30d is computed on the primary series only.

Parameters

  • id — required. One providerId (1–80 characters: A–Z a–z 0–9 _ - : .).

Request:

curl "https://cards.faseconsulting.es/api/public/card-summary/?id=sv1-258"

Response 200:

{
  "providerId": "sv1-258",
  "game": "pokemon",
  "name": "Basic Fighting Energy",
  "setCode": "sv1",
  "setName": "Scarlet & Violet",
  "number": "258",
  "rarity": "Hyper Rare",
  "imageUrl": "https://images.pokemontcg.io/sv1/258_hires.png",
  "path": "/pokemon/sv1/basic-fighting-energy-258/",
  "primary": {
    "amount": 4.76,
    "currency": "EUR",
    "source": "cardmarket",
    "capturedAt": "2026-07-11T03:45:50.476Z"
  },
  "secondary": {
    "amount": 7.35,
    "currency": "USD",
    "source": "tcgplayer",
    "capturedAt": "2026-07-11T03:45:50.476Z"
  },
  "delta30d": 4.2857142857142785
}

Errors

  • 400{"error":"expected ?id=<providerId>"} (id missing or with invalid characters)
  • 404{"error":"card_not_found"}

CDN cache: Cache-Control: public, s-maxage=300, stale-while-revalidate=600.

GET /api/public/set-completion/

No authentication

Set-completion snapshot: total prints, full-set value and a providerId → price map, all in ONE currency (whichever prices the most cards of the set; EUR on ties). Designed for client-side completion math without uploading your owned list: missing = totalCards − owned; cost = totalValue − Σ prices[id]. Cards unpriced in that currency are absent from the map.

Parameters

  • game — required. One of: mtg · pokemon · yugioh · lorcana · onepiece · swu · digimon.
  • setCode — required. Set code (1–40 characters: A–Z a–z 0–9 space _ - .).

If the set exceeds 3,000 prints the response ships oversized: true with an empty prices map (safety valve; the totals are still returned).

Request:

curl "https://cards.faseconsulting.es/api/public/set-completion/?game=pokemon&setCode=sv1"

Response 200:

{
  "game": "pokemon",
  "setCode": "sv1",
  "setName": "Scarlet & Violet",
  "totalCards": 258,
  "pricedCards": 258,
  "currency": "USD",
  "totalValue": 853.08,
  "prices": {
    "sv1-1": 0.12,
    "sv1-2": 0.11,
    … 258 entries (providerId → amount) …
  },
  "oversized": false
}

Errors

  • 400{"error":"expected ?game=<TcgGame>&setCode=<code>"}
  • 404{"error":"set_not_found"}

CDN cache: Cache-Control: public, s-maxage=600, stale-while-revalidate=3600 (404s are cached for 300 s).

Authentication & API keys

The cards endpoint requires an API key. Keys are free: sign in, open your account page (“API keys” section) and generate one — the key (cm_ prefix) is shown ONCE; if you lose it, revoke it and create a new one.

What a key unlocks today: the GET /api/public/cards/{providerId} endpoint (full card record + latest price). The batch prices endpoint stays anonymous.

Create an API key in your account →

Rate limits

Each key gets its own token bucket: 1,000 requests/hour by default (configurable between 10 and 10,000 at creation time). Every response carries x-ratelimit-limit and x-ratelimit-remaining headers; when exhausted you get 429 with Retry-After. The anonymous prices endpoint is CDN-cached for 5 minutes — sort your ids so identical requests share a cache key, and keep your polling reasonable.

Where do providerIds come from?

They are the canonical ids of each card printing (for Magic, the Scryfall UUID). You can discover them with the internal search endpoint GET /api/search?q=… (the i field of each result) — that endpoint is internal and its shape may change without notice; the /api/public/ endpoints on this page are stable (breaking changes will ship under /v2/).

Attribution (required)

If you publish data obtained from this API you must attribute it to CardMetrics with a visible link to cards.faseconsulting.es (e.g. “Data from CardMetrics”).

Our data is built on upstream sources that require attribution too — keep it flowing downstream when you display their data:

  • Prices: Cardmarket (EUR) and TCGplayer (USD, via TCGCSV).
  • Catalogs: Scryfall (Magic), pokemontcg.io and TCGdex (Pokémon), YGOPRODeck (Yu-Gi-Oh!), Lorcast (Lorcana), OPTCG API (One Piece), SWU-DB (Star Wars: Unlimited) and DigimonCard.io (Digimon).
  • Images (imageUrl) are served from each source's official CDN and remain subject to their terms — hotlink them, don't copy them.

Fair use

  • Identify yourself with a descriptive User-Agent (project name + contact).
  • No bulk mirroring or resale of the data; the API is for apps, bots and integrations, not for replicating the database.
  • Prices are informational (secondary market), not purchase advice.