# magi API — Japan's trading-card marketplace (マギ, magi.camp): live and SOLD listings with the price they sold at, every card's trade history (each sale's price + dated daily chart), cheapest live price per card, listing detail with seller rating, Pokémon, One Piece, Yu-Gi-Oh!, Duel Masters, MTG, Weiß Schwarz and 200+ games. JPY. No login, no key.

> Search magi listings: keyword, game, sub-category (singles, unopened boxes, packs, old-back …), new/used, price range, live or sold, one card product, one seller, graded (PSA10 …), sorted newest / cheapest / dearest / most favourited, 96 a page. Every row carries the SOLD flag.
> ReefAPI engine `magi` · 9 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/magi/v1/<action>` with a JSON body.
- **Auth:** header `x-api-key: <YOUR_REEFAPI_KEY>` — create one free (1,000 credits, no card): https://reefapi.com/signup
- **Response (every call):** `{ ok: boolean, data: ..., meta: { record_count, credits, ... }, error: { code, message } }` — branch on `ok`. Failed calls are free.
- **One key + one shared credit pool** across every ReefAPI API. Per-call credits are listed on each endpoint below.
- **Use it from an AI agent (MCP):** connect `https://api.reefapi.com/mcp` (remote streamable-http). Clients that add connectors by URL, such as ChatGPT and the Claude app, connect with OAuth 2.1 (the user pastes their key once on a ReefAPI page; discovery at `/.well-known/oauth-protected-resource/mcp`). Config files send the key as `Authorization: Bearer <key>`. `?key=<key>` in the URL also works as a last-resort fallback.

## Endpoints

### POST https://api.reefapi.com/magi/v1/search — 2 credits
Search magi listings: keyword, game, sub-category (singles, unopened boxes, packs, old-back …), new/used, price range, live or sold, one card product, one seller, graded (PSA10 …), sorted newest / cheapest / dearest / most favourited, 96 a page. Every row carries the SOLD flag.

**Parameters:**
- `query` (string, optional) — Keyword as sellers write it (Japanese works best: card name, card number such as '134/108' or 'OP05-119', set name, 'PSA10', 'BOX', '未開封'). Matched in the listing title (and in the description with include_description).
- `game` (enum, optional) — Card game (magi 'brand'): pokemon, one_piece, yugioh, duel_masters, mtg, weiss_schwarz, union_arena, digimon, lorcana, sports … or any numeric game id from `categories` (200+ games). [one of: pokemon, one_piece, yugioh, duel_masters, mtg, weiss_schwarz, weiss_schwarz_blau, weiss_schwarz_rose, union_arena, digimon, shadowverse_evolve, dragon_ball_fusion_world, dragon_ball_heroes, battle_spirits, vanguard, lorcana, gundam, hololive, flesh_and_blood, wixoss, naruto, love_live, godzilla, ultraman, rebirth, zx, buddyfight, detective_conan, sports, bikkuriman, mushiking, supplies]
- `series_id` (string, optional) — Sub-category of a game from `categories` with game=… (e.g. Pokémon 31 singles, 100058 unopened boxes, 100562 unopened packs, 100002 old-back cards, 100007 overseas versions).
- `category` (enum, optional) — magi's top category: cards (トレカ), sneakers, hobby, video_games, nft. Default: the whole site (almost all cards). [one of: cards, sneakers, nft, hobby, video_games]
- `condition` (enum, optional) — new (新品, incl. unopened boxes) or used (中古). [one of: new, used]
- `min_price` (integer, optional) — Lowest listing price, JPY (inclusive; price as shown, buyer fee included).
- `max_price` (integer, optional) — Highest listing price, JPY (inclusive).
- `status` (enum, optional, default "all") — Live listings, sold listings, or both. [one of: all, on_sale, sold]
- `include_description` (boolean, optional, default false) — Also match the keyword inside the listing description (商品説明を含める).
- `product_id` (string, optional) — Only listings of one card product (a `products` / `catalog` row's product_id, or a magi.camp/products/<id> URL).
- `seller_id` (string, optional) — Only one seller's listings (item.seller.seller_id, or a magi.camp/users/<id> URL).
- `grade` (string, optional) — Graded slabs only: grader + grade as sellers write it (PSA10, PSA9, BGS9.5, ARS10+, CGC10). Added to the keyword — magi has no separate grade filter — and every row's `grade` is parsed from its title.
- `sort` (enum, optional, default "newest") — Order of results. [one of: newest, oldest, price_asc, price_desc, most_favorited]
- `page` (integer, optional, default 1) — Page number, 96 rows a page. magi serves at most 100 pages (9,600 rows) per query.

**Returns:** rows[]: item_id, title (as the seller wrote it, Japanese kept), price_jpy (price as shown: tax and buyer fee included; on a sold row = the price it sold at), sold (true = SOLD OUT), favorites, certified_seller (認定出品者 = registered shop), grade{grader, grade, label} (parsed from the title; null when ungraded), image_url, url. meta: total (the site's own count; capped at 10000 by the site), total_capped, products_total, page, per_page (96), last_page, has_more, filters_applied, promoted[] (listings the site pins above the results on the default sort — not part of the results), warnings.

**Example request body:**
```json
{
  "query": "リザードン",
  "game": "pokemon"
}
```

### POST https://api.reefapi.com/magi/v1/sold — 2 credits
Sold listings only — what cards actually SOLD for on magi (the realised price, buyer fee included), newest sales first by default: the price check / arbitrage feed. Same filters as search; meta.price_summary gives count, min, median, mean and max of the page's sold prices.

**Parameters:**
- `query` (string, optional) — Keyword as sellers write it (Japanese works best: card name, card number such as '134/108' or 'OP05-119', set name, 'PSA10', 'BOX', '未開封'). Matched in the listing title (and in the description with include_description).
- `game` (enum, optional) — Card game (magi 'brand'): pokemon, one_piece, yugioh, duel_masters, mtg, weiss_schwarz, union_arena, digimon, lorcana, sports … or any numeric game id from `categories` (200+ games). [one of: pokemon, one_piece, yugioh, duel_masters, mtg, weiss_schwarz, weiss_schwarz_blau, weiss_schwarz_rose, union_arena, digimon, shadowverse_evolve, dragon_ball_fusion_world, dragon_ball_heroes, battle_spirits, vanguard, lorcana, gundam, hololive, flesh_and_blood, wixoss, naruto, love_live, godzilla, ultraman, rebirth, zx, buddyfight, detective_conan, sports, bikkuriman, mushiking, supplies]
- `series_id` (string, optional) — Sub-category of a game from `categories` with game=… (e.g. Pokémon 31 singles, 100058 unopened boxes, 100562 unopened packs, 100002 old-back cards, 100007 overseas versions).
- `category` (enum, optional) — magi's top category: cards (トレカ), sneakers, hobby, video_games, nft. Default: the whole site (almost all cards). [one of: cards, sneakers, nft, hobby, video_games]
- `condition` (enum, optional) — new (新品, incl. unopened boxes) or used (中古). [one of: new, used]
- `min_price` (integer, optional) — Lowest listing price, JPY (inclusive; price as shown, buyer fee included).
- `max_price` (integer, optional) — Highest listing price, JPY (inclusive).
- `include_description` (boolean, optional, default false) — Also match the keyword inside the listing description (商品説明を含める).
- `product_id` (string, optional) — Only listings of one card product (a `products` / `catalog` row's product_id, or a magi.camp/products/<id> URL).
- `seller_id` (string, optional) — Only one seller's listings (item.seller.seller_id, or a magi.camp/users/<id> URL).
- `grade` (string, optional) — Graded slabs only: grader + grade as sellers write it (PSA10, PSA9, BGS9.5, ARS10+, CGC10). Added to the keyword — magi has no separate grade filter — and every row's `grade` is parsed from its title.
- `sort` (enum, optional, default "newest") — Order of results. [one of: newest, oldest, price_asc, price_desc, most_favorited]
- `page` (integer, optional, default 1) — Page number, 96 rows a page. magi serves at most 100 pages (9,600 rows) per query.

**Returns:** rows[]: item_id, title (as the seller wrote it, Japanese kept), price_jpy (price as shown: tax and buyer fee included; on a sold row = the price it sold at), sold (true = SOLD OUT), favorites, certified_seller (認定出品者 = registered shop), grade{grader, grade, label} (parsed from the title; null when ungraded), image_url, url (sold is always true). meta: total, total_capped, page, per_page, last_page, has_more, price_summary{count, min_jpy, max_jpy, median_jpy, mean_jpy}, filters_applied, promoted[] (unsold listings the site pins on top — excluded), warnings.

**Example request body:**
```json
{
  "query": "ルフィ",
  "game": "one_piece"
}
```

### POST https://api.reefapi.com/magi/v1/item — 2 credits
One magi listing in full: price with and without the buyer fee, SOLD flag, condition, quantity, the card product it is listed under, shipping (fee included or not, method, anonymous shipping, ships from prefecture, dispatch time), the seller's public profile (name, id, identity check, rank, good / normal / bad rating counts, registered shop / real store), description, all photos and last-update time.

**Parameters:**
- `item_id` (string, required) — Listing id (a search row's item_id) or a magi.camp/items/<id> URL.

**Returns:** item{item_id, url, title, sold, availability (InStock / OutOfStock …), buy_button, price_jpy (tax + buyer fee included), price_excl_fee_jpy, buyer_fee_jpy, tax_included, currency, condition (状態 as printed), condition_code (new|used), quantity, quantity_label, category, game, series, product{product_id, name, url} (null when the seller linked no card), grade{grader, grade, label}, shipping_fee, shipping_included, shipping_method, shipping_tags[] (匿名配送 …), ships_from, ships_within, attributes{label: value}, tags[], certified_seller, real_store, seller{seller_id, name, url, identity_verified, rank_level, ratings{good, normal, bad}}, last_updated (relative, as printed), description, images[], image_url}

**Example request body:**
```json
{
  "item_id": "2121835655"
}
```

### POST https://api.reefapi.com/magi/v1/products — 2 credits
Search magi's card catalogue (製品): one row per card / box / graded slab with the cheapest live listing price and the number of listings — the fastest way to find a product_id for price history. Keyword, game, sub-category, price range, sort, 96 a page.

**Parameters:**
- `query` (string, optional) — Keyword as sellers write it (Japanese works best: card name, card number such as '134/108' or 'OP05-119', set name, 'PSA10', 'BOX', '未開封'). Matched in the listing title (and in the description with include_description).
- `game` (enum, optional) — Card game (magi 'brand'): pokemon, one_piece, yugioh, duel_masters, mtg, weiss_schwarz, union_arena, digimon, lorcana, sports … or any numeric game id from `categories` (200+ games). [one of: pokemon, one_piece, yugioh, duel_masters, mtg, weiss_schwarz, weiss_schwarz_blau, weiss_schwarz_rose, union_arena, digimon, shadowverse_evolve, dragon_ball_fusion_world, dragon_ball_heroes, battle_spirits, vanguard, lorcana, gundam, hololive, flesh_and_blood, wixoss, naruto, love_live, godzilla, ultraman, rebirth, zx, buddyfight, detective_conan, sports, bikkuriman, mushiking, supplies]
- `series_id` (string, optional) — Sub-category of a game from `categories` with game=… (e.g. Pokémon 31 singles, 100058 unopened boxes, 100562 unopened packs, 100002 old-back cards, 100007 overseas versions).
- `category` (enum, optional) — magi's top category: cards (トレカ), sneakers, hobby, video_games, nft. Default: the whole site (almost all cards). [one of: cards, sneakers, nft, hobby, video_games]
- `min_price` (integer, optional) — Lowest cheapest-listing price, JPY.
- `max_price` (integer, optional) — Highest cheapest-listing price, JPY.
- `sort` (enum, optional, default "newest") — Order of results. [one of: newest, oldest, price_asc, price_desc, most_favorited]
- `page` (integer, optional, default 1) — Page number, 96 rows a page. magi serves at most 100 pages (9,600 rows) per query.

**Returns:** rows[]: product_id, name (card name + rarity + number, grade prefix such as 【PSA10】 kept), min_price_jpy (cheapest live listing; null = none listed now), listing_count, grade{grader, grade, label}, image_url, url. meta: total, total_capped, listings_total, page, per_page (96), last_page, has_more, filters_applied, warnings.

**Example request body:**
```json
{
  "query": "リザードン"
}
```

### POST https://api.reefapi.com/magi/v1/product — 2 credits
One card product with its sold-price history: every completed sale (price, quantity, how long ago), the dated daily price chart, last sale, the site's 12-month price range and all-time average, the cheapest live price, rarity / set (pack) / card number, the live and recently sold listings, and the same card in other grades (PSA10, PSA9, ARS10 …) with their prices.

**Parameters:**
- `product_id` (string, required) — Card product id (from `products`, `catalog` or a listing's product.product_id) or a magi.camp/products/<id> URL.

**Returns:** product{product_id, url, name, short_name, grade, goods{goods_id, name}, game{game_id, name, alias}, series{series_id, name}, rarity, pack_name, model_number, attributes{}, min_price_jpy, currency, trade_count, last_trade_date, last_trade_price_jpy, range_12m_min_jpy, range_12m_max_jpy, average_all_time_jpy (the site's figures), median_all_trades_jpy, trades[]{age (as printed), days_ago, date (only when exact), price_jpy, quantity, quantity_label}, daily_chart[]{date, price_jpy} (one point per day, newest first, at most 200 days), trade_dates_exact, listings[] (item_id, title (as the seller wrote it, Japanese kept), price_jpy (price as shown: tax and buyer fee included; on a sold row = the price it sold at), sold (true = SOLD OUT), favorites, certified_seller (認定出品者 = registered shop), grade{grader, grade, label} (parsed from the title; null when ungraded), image_url, url), other_grades[]{product_id, name, min_price_jpy, listing_count, grade, image_url, url}, image_url}

**Example request body:**
```json
{
  "product_id": "422598"
}
```

### POST https://api.reefapi.com/magi/v1/price_history — 2 credits
A card's sold-price history ready for charts and price checks: the dated daily series (optionally only the last N days), every sale with its price, and a summary — count, min, median, mean, max, first and last date, change from first to last — plus the site's own 12-month range and all-time average.

**Parameters:**
- `product_id` (string, required) — Card product id (from `products`, `catalog` or a listing's product.product_id) or a magi.camp/products/<id> URL.
- `days` (integer, optional) — Only the chart's last N days (counted back from today, Japan time) for the summary and the series. Default: everything the page shows.

**Returns:** product{product_id, name, rarity, pack_name, model_number, game, url}, series[]{date, price_jpy} (newest first), summary{points, first_date, last_date, first_price_jpy, last_price_jpy, change_jpy, change_percent, min_jpy, max_jpy, median_jpy, mean_jpy}, trades[]{age, days_ago, date, price_jpy, quantity}, trade_count, range_12m_min_jpy, range_12m_max_jpy, average_all_time_jpy, days, currency

**Example request body:**
```json
{
  "product_id": "422598"
}
```

### POST https://api.reefapi.com/magi/v1/catalog — 1 credit
magi's card database lookup: card products matching a name or number with their rarity, card number (型番), set / pack (封入パック), game and sub-category — 96 a page. Turns a card name into the product_id that `product` and `price_history` take.

**Parameters:**
- `query` (string, required) — Card name, card number or set name (Japanese works best).
- `series_id` (string, optional) — Sub-category of a game from `categories` with game=… (e.g. Pokémon 31 singles, 100058 unopened boxes, 100562 unopened packs, 100002 old-back cards, 100007 overseas versions).
- `page` (integer, optional, default 1) — Page number, 96 products a page.

**Returns:** rows[]: product_id, name, full_name, rarity, model_number, pack_name, grade, game{game_id, name, alias}, series{series_id, name}, image_url, url. meta: page, per_page (96), has_more.

**Example request body:**
```json
{
  "query": "リザードン"
}
```

### POST https://api.reefapi.com/magi/v1/categories — 1 credit
magi's category tree: the top categories (cards, sneakers …) and every card game with its id (200+: Pokémon, One Piece, Yu-Gi-Oh!, Duel Masters, MTG, Weiß Schwarz, Lorcana, sports …); with game=… also that game's sub-categories (singles, unopened boxes, packs, old-back, overseas …) and the conditions each allows. Ids go to search as game / series_id.

**Parameters:**
- `game` (enum, optional) — List this game's sub-categories (series). [one of: pokemon, one_piece, yugioh, duel_masters, mtg, weiss_schwarz, weiss_schwarz_blau, weiss_schwarz_rose, union_arena, digimon, shadowverse_evolve, dragon_ball_fusion_world, dragon_ball_heroes, battle_spirits, vanguard, lorcana, gundam, hololive, flesh_and_blood, wixoss, naruto, love_live, godzilla, ultraman, rebirth, zx, buddyfight, detective_conan, sports, bikkuriman, mushiking, supplies]

**Returns:** goods[]{goods_id, name, alias}, games[]{game_id, name, alias}, game{game_id, name, alias}, series[]{series_id, name, conditions[]} (with game), aliases{games{alias: id}}

**Example request body:**
```json
{
  "game": "pokemon"
}
```

### POST https://api.reefapi.com/magi/v1/trending — 1 credit
What magi users are searching for right now (the site's trending keywords).

**Parameters:** none

**Returns:** rows[]: rank, keyword, search_url

## At scale
- **Volume:** 5M+ requests a day, measured at 60 requests a second across the fleet with no
  central bottleneck. Per-key limits are raised for high-volume accounts; volume pricing on request.
- **Missing a source:** tell us a site we do not cover and it becomes an engine. A customer asked
  for bestprice.gr on 21 Sep 2026 and it was in the catalog on 22 Sep.
- **Support:** 2 minute median time from a question in the live chat to the first answer. Setup
  help included, no support tier to buy.
- **One key, one credit pool** across every API. No per-site plans, no separate subscriptions.

## More
- Try it live, no code: https://reefapi.com/playground?engine=magi
- Human docs page: https://reefapi.com/docs/magi
- Overview page: https://reefapi.com/magi-api
- Every ReefAPI API in one file (for your AI): https://reefapi.com/llms-full.txt
